Merge branch 'fcs-ql' of
ssh://margaretha@korap.ids-mannheim.de:29418/KorAP/Koral into fcs-ql

Conflicts:
	src/main/java/de/ids_mannheim/korap/query/serialize/QuerySerializer.java

Change-Id: Id1037d133c9fa6ea7cb4e07f0ae32ed978671c18
diff --git a/Changes b/Changes
index 8cc2db8..2747707 100644
--- a/Changes
+++ b/Changes
@@ -1,7 +1,16 @@
-0.2 2015-10-27
-        - Switch to "koral:" prefix.
+0.22 2016-06-03
+        - Spans now always wrap terms (diewald)
+	- Cosmas-II "und", "oder", and "nicht" operations
+	  now serialize to unordered sequences (diewald)
+
+0.21 2015-10-27
+        - Improved meta query builder (hanl)
+
+0.2 2015-06-25
+        - Switch to "koral:" prefix (bingel)
 	- Coverage of KoralQuery 0.3
 	  (see http://korap.github.io/Koral/)
+          (bingel)
 
 0.1 2015-02-10
-        - First version published to GitHub.
+        - First version published to GitHub (bingel)
diff --git a/pom.xml b/pom.xml
index 692be5f..00f257e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
 
   <groupId>de.ids_mannheim.korap</groupId>
   <artifactId>Koral</artifactId>
-  <version>0.21</version>
+  <version>0.22</version>
   <packaging>jar</packaging>
   <name>Koral</name>
   <url>http://maven.apache.org</url>
@@ -29,6 +29,11 @@
     </dependency>
     <dependency>
       <groupId>org.antlr</groupId>
+      <artifactId>antlr4-runtime</artifactId>
+      <version>4.5.1</version>
+    </dependency>
+    <dependency>
+      <groupId>org.antlr</groupId>
       <artifactId>antlr4-maven-plugin</artifactId>
       <version>4.2</version>
     </dependency>
@@ -75,11 +80,6 @@
       <version>1.12</version>
     </dependency>
     <dependency>
-      <groupId>org.projectlombok</groupId>
-      <artifactId>lombok</artifactId>
-      <version>0.11.8</version>
-    </dependency>
-    <dependency>
       <groupId>log4j</groupId>
       <artifactId>log4j</artifactId>
       <version>1.2.17</version>
diff --git a/src/main/antlr/poliqarpplus/PoliqarpPlusLexer.g4 b/src/main/antlr/poliqarpplus/PoliqarpPlusLexer.g4
index f8b5d91..68c0bef 100644
--- a/src/main/antlr/poliqarpplus/PoliqarpPlusLexer.g4
+++ b/src/main/antlr/poliqarpplus/PoliqarpPlusLexer.g4
@@ -60,10 +60,8 @@
 
 NL                  : [\r\n] -> skip;
 
-
 WORD                : ALPHABET+;
 
-
 /* Complex queries */
 LPAREN      : '[';
 RPAREN      : ']';
@@ -101,4 +99,5 @@
 fragment RE_expr     : ('.' | RE_char | RE_alter | RE_chgroup | RE_opt | RE_quant | RE_group)+;
 fragment RE_dquote            : '"'  (RE_expr | '\'' | ':' )* '"';
 fragment RE_squote            : '\''  (RE_expr | '\"' | ':' )* '\'';
-REGEX             : ( RE_dquote | RE_squote );
\ No newline at end of file
+ 
+REGEX             : ( RE_dquote | RE_squote | );
diff --git a/src/main/antlr/poliqarpplus/PoliqarpPlusParser.g4 b/src/main/antlr/poliqarpplus/PoliqarpPlusParser.g4
index 9e9c595..c48a3f9 100644
--- a/src/main/antlr/poliqarpplus/PoliqarpPlusParser.g4
+++ b/src/main/antlr/poliqarpplus/PoliqarpPlusParser.g4
@@ -231,4 +231,4 @@
     Entry point for all requests. Linguistic query is obligatory, metadata filtering
     is optional.
 */
-request            : query within? meta? EOF;
\ No newline at end of file
+request            : query within? meta? EOF;
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/CollectionQueryProcessor.java b/src/main/java/de/ids_mannheim/korap/query/serialize/CollectionQueryProcessor.java
index e051e19..ae544a1 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/CollectionQueryProcessor.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/CollectionQueryProcessor.java
@@ -25,7 +25,7 @@
  * of the KoralQuery tree. See the official documentation for VC query
  * syntax
  * and functionality.
- *
+ * 
  * @author Michael Hanl (hanl@ids-mannheim.de)
  * @author Joachim Bingel (bingel@ids-mannheim.de)
  * @version 0.3.0
@@ -36,26 +36,31 @@
     private static Logger log = LoggerFactory
             .getLogger(CollectionQueryProcessor.class);
 
-    public CollectionQueryProcessor() {
+
+    public CollectionQueryProcessor () {
         KoralObjectGenerator.setQueryProcessor(this);
     }
 
-    public CollectionQueryProcessor(boolean verbose) {
+
+    public CollectionQueryProcessor (boolean verbose) {
         KoralObjectGenerator.setQueryProcessor(this);
         CollectionQueryProcessor.verbose = verbose;
     }
 
-    public CollectionQueryProcessor(String query) {
+
+    public CollectionQueryProcessor (String query) {
         KoralObjectGenerator.setQueryProcessor(this);
         process(query);
     }
 
+
     @Override
-    public void process(String query) {
+    public void process (String query) {
         ParseTree tree = parseCollectionQuery(query);
         if (this.parser != null) {
             super.parser = this.parser;
-        }else {
+        }
+        else {
             throw new NullPointerException("Parser has not been instantiated!");
         }
         log.info("Processing virtual collection query: " + query);
@@ -64,13 +69,15 @@
         if (tree != null) {
             log.debug("ANTLR parse tree: " + tree.toStringTree(parser));
             processNode(tree);
-        }else {
-            addError(StatusCodes.MALFORMED_QUERY,
-                    "Could not parse query >>> " + query + " <<<.");
+        }
+        else {
+            addError(StatusCodes.MALFORMED_QUERY, "Could not parse query >>> "
+                    + query + " <<<.");
         }
     }
 
-    private void processNode(ParseTree node) {
+
+    private void processNode (ParseTree node) {
         // Top-down processing
         String nodeCat = getNodeCat(node);
         openNodeCats.push(nodeCat);
@@ -90,8 +97,8 @@
          */
 
         if (nodeCat.equals("relation")) {
-            String operator = getNodeCat(node.getChild(1).getChild(0))
-                    .equals("&") ? "and" : "or";
+            String operator = getNodeCat(node.getChild(1).getChild(0)).equals(
+                    "&") ? "and" : "or";
             LinkedHashMap<String, Object> relationGroup = KoralObjectGenerator
                     .makeDocGroup(operator);
             putIntoSuperObject(relationGroup);
@@ -114,14 +121,14 @@
                 requestMap = new LinkedHashMap<String, Object>();
                 return;
             }
-//            if (QueryUtils.checkDateValidity(valueNode.getText())) {
-//                addWarning("The collection query contains a value that looks"
-//                        + " like a date ('" + valueNode.getText() + "') and an"
-//                        + " operator that is only defined for strings" + " ('"
-//                        + match + "'). The value is interpreted as"
-//                        + " a string. Use a date operator to ensure the value"
-//                        + " is treated as a date");
-//            }
+            //            if (QueryUtils.checkDateValidity(valueNode.getText())) {
+            //                addWarning("The collection query contains a value that looks"
+            //                        + " like a date ('" + valueNode.getText() + "') and an"
+            //                        + " operator that is only defined for strings" + " ('"
+            //                        + match + "'). The value is interpreted as"
+            //                        + " a string. Use a date operator to ensure the value"
+            //                        + " is treated as a date");
+            //            }
 
             putIntoSuperObject(term);
         }
@@ -192,7 +199,8 @@
                     }
                 }
                 token.put("wrap", term);
-            }else {
+            }
+            else {
                 // child is 'term' or 'termGroup' -> process in extra method 
                 LinkedHashMap<String, Object> termOrTermGroup = parseTermOrTermGroup(
                         node.getChild(1), negated);
@@ -231,18 +239,19 @@
 
     }
 
+
     /**
      * Checks whether the combination of operator and value is legal
      * (inequation operators <,>,<=,>= may only be used with dates).
      */
-    private boolean checkOperatorValueConformance(
+    private boolean checkOperatorValueConformance (
             LinkedHashMap<String, Object> term) {
         String match = (String) term.get("match");
         String type = (String) term.get("type");
         if (type == null || type.equals("type:regex")) {
-            if (!(match.equals("match:eq") || match.equals("match:ne") || match
-                    .equals("match:contains") || match
-                    .equals("match:containsnot"))) {
+            if (!(match.equals("match:eq") || match.equals("match:ne")
+                    || match.equals("match:contains") || match
+                        .equals("match:containsnot"))) {
                 addError(StatusCodes.INCOMPATIBLE_OPERATOR_AND_OPERAND,
                         "You used an inequation operator with a string value.");
                 return false;
@@ -251,7 +260,8 @@
         return true;
     }
 
-    private LinkedHashMap<String, Object> parseValue(ParseTree valueNode) {
+
+    private LinkedHashMap<String, Object> parseValue (ParseTree valueNode) {
         LinkedHashMap<String, Object> map = new LinkedHashMap<String, Object>();
         if (getNodeCat(valueNode).equals("date")) {
             map.put("type", "type:date");
@@ -261,6 +271,7 @@
 
         TokenStream stream = parser.getTokenStream();
         String stm = stream.getText(valueNode.getChild(0).getSourceInterval());
+        // todo: is this correct?
         if (stm.startsWith("\"") && stm.endsWith("\""))
             stm = stm.replaceAll("\"", "");
 
@@ -274,15 +285,16 @@
         return map;
     }
 
+
     /**
      * Checks if value is a date
-     *
+     * 
      * @param valueNode
      * @return
      */
 
     @Deprecated
-    private boolean checkDateValidity(ParseTree valueNode) {
+    private boolean checkDateValidity (ParseTree valueNode) {
         Pattern p = Pattern.compile("[0-9]{4}(-([0-9]{2})(-([0-9]{2}))?)?");
         Matcher m = p.matcher(valueNode.getText());
 
@@ -293,7 +305,8 @@
         if (month != null) {
             if (Integer.parseInt(month) > 12) {
                 return false;
-            }else if (day != null) {
+            }
+            else if (day != null) {
                 if (Integer.parseInt(day) > 31) {
                     return false;
                 }
@@ -302,7 +315,8 @@
         return true;
     }
 
-    private String interpretMatchOperator(String match) {
+
+    private String interpretMatchOperator (String match) {
         String out = null;
         switch (match) {
             case "<":
@@ -350,8 +364,9 @@
         return out;
     }
 
+
     @Deprecated
-    private String invertInequation(String op) {
+    private String invertInequation (String op) {
         String inv = null;
         switch (op) {
             case "lt":
@@ -370,41 +385,47 @@
         return inv;
     }
 
-    private void putIntoSuperObject(LinkedHashMap<String, Object> object) {
+
+    private void putIntoSuperObject (LinkedHashMap<String, Object> object) {
         putIntoSuperObject(object, 0);
     }
 
+
     @SuppressWarnings({ "unchecked" })
-    private void putIntoSuperObject(LinkedHashMap<String, Object> object,
+    private void putIntoSuperObject (LinkedHashMap<String, Object> object,
             int objStackPosition) {
         if (objectStack.size() > objStackPosition) {
             ArrayList<Object> topObjectOperands = (ArrayList<Object>) objectStack
                     .get(objStackPosition).get("operands");
             topObjectOperands.add(object);
-        }else {
+        }
+        else {
             //        	requestMap = object;
             requestMap.put("collection", object);
         }
     }
 
-    private LinkedHashMap<String, Object> parseTermOrTermGroup(ParseTree node,
+
+    private LinkedHashMap<String, Object> parseTermOrTermGroup (ParseTree node,
             boolean negated) {
         return parseTermOrTermGroup(node, negated, "token");
     }
 
+
     /**
      * Parses a (term) or (termGroup) node
-     *
+     * 
      * @param node
-     * @param negatedGlobal Indicates whether the term/termGroup is globally
-     *                      negated, e.g. through a negation operator preceding
-     *                      the related token
-     *                      like "![base=foo]". Global negation affects the
-     *                      "match" parameter.
+     * @param negatedGlobal
+     *            Indicates whether the term/termGroup is globally
+     *            negated, e.g. through a negation operator preceding
+     *            the related token
+     *            like "![base=foo]". Global negation affects the
+     *            "match" parameter.
      * @return A term or termGroup object, depending on input
      */
     @SuppressWarnings("unchecked")
-    private LinkedHashMap<String, Object> parseTermOrTermGroup(ParseTree node,
+    private LinkedHashMap<String, Object> parseTermOrTermGroup (ParseTree node,
             boolean negatedGlobal, String mode) {
         if (getNodeCat(node).equals("term")) {
             String key = null;
@@ -478,7 +499,8 @@
                 }
             }
             return term;
-        }else {
+        }
+        else {
             // For termGroups, establish a boolean relation between operands 
             // and recursively call this function with the term or termGroup 
             // operands.
@@ -508,7 +530,8 @@
         }
     }
 
-    private ParserRuleContext parseCollectionQuery(String query) {
+
+    private ParserRuleContext parseCollectionQuery (String query) {
         Lexer lexer = new CollectionQueryLexer((CharStream) null);
         ParserRuleContext tree = null;
         Antlr4DescriptiveErrorListener errorListener = new Antlr4DescriptiveErrorListener(
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/Cosmas2QueryProcessor.java b/src/main/java/de/ids_mannheim/korap/query/serialize/Cosmas2QueryProcessor.java
index 1b22f39..fbf63ac 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/Cosmas2QueryProcessor.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/Cosmas2QueryProcessor.java
@@ -669,6 +669,7 @@
         // Step I: create group
         LinkedHashMap<String, Object> disjunction = KoralObjectGenerator
                 .makeGroup("disjunction");
+        disjunction.put("inOrder", false); // Order is not important 
         objectStack.push(disjunction);
         stackedObjects++;
         // Step II: decide where to put
@@ -681,6 +682,7 @@
         String nodeCat = getNodeCat(node);
         LinkedHashMap<String, Object> distgroup = KoralObjectGenerator
                 .makeGroup("sequence");
+        distgroup.put("inOrder", false); // Order is not important 
         ArrayList<Object> distances = new ArrayList<Object>();
         LinkedHashMap<String, Object> zerodistance = KoralObjectGenerator
                 .makeDistance("t", 0, 0);
@@ -1350,4 +1352,4 @@
         }
         return tree;
     }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/MetaQueryBuilder.java b/src/main/java/de/ids_mannheim/korap/query/serialize/MetaQueryBuilder.java
index f743aba..cad4319 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/MetaQueryBuilder.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/MetaQueryBuilder.java
@@ -1,7 +1,5 @@
 package de.ids_mannheim.korap.query.serialize;
 
-import lombok.Data;
-
 import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.List;
@@ -19,41 +17,45 @@
     private Map meta;
     private SpanContext spanContext;
 
-    public MetaQueryBuilder() {
+
+    public MetaQueryBuilder () {
         this.meta = new LinkedHashMap();
         //        this.meta.put("fields", new LinkedList<>());
     }
 
+
     /**
      * context segment if context is either of type char or token.
      * size can differ for left and right span
-     *
+     * 
      * @param left
      * @param leftType
      * @param right
      * @param rightType
      * @return
      */
-    public MetaQueryBuilder setSpanContext(Integer left, String leftType,
+    public MetaQueryBuilder setSpanContext (Integer left, String leftType,
             Integer right, String rightType) {
         this.spanContext = new SpanContext(left, leftType, right, rightType);
         return this;
     }
 
-    public SpanContext getSpanContext() {
+
+    public SpanContext getSpanContext () {
         return this.spanContext;
     }
 
+
     /**
      * context if of type paragraph or sentence where left and right
      * size delimiters are irrelevant; or 2-token, 2-char p/paragraph,
      * s/sentence or token, char.
      * Distinguish
-     *
+     * 
      * @param context
      * @return
      */
-    public MetaQueryBuilder setSpanContext(String context) {
+    public MetaQueryBuilder setSpanContext (String context) {
         if (context != null) {
             if (!p.matcher(context).find())
                 this.spanContext = new SpanContext(context);
@@ -68,19 +70,20 @@
         return this;
     }
 
-    public MetaQueryBuilder addEntry(String name, Object value) {
+
+    public MetaQueryBuilder addEntry (String name, Object value) {
         if (value != null)
             meta.put(name, value);
         return this;
     }
 
-    public Map raw() {
+
+    public Map raw () {
         if (this.spanContext != null)
             meta.putAll(this.spanContext.raw());
         return meta;
     }
 
-    @Data
     public class SpanContext {
         private String left_type;
         private String right_type;
@@ -88,27 +91,45 @@
         private int right_size;
         private String context = null;
 
+
         /**
          * context segment if context is either of type char or token.
          * size can differ for left and right span
-         *
+         * 
          * @param ls
          * @param lt
          * @param rs
          * @param rt
          * @return
          */
-        public SpanContext(int ls, String lt, int rs, String rt) {
+        public SpanContext (int ls, String lt, int rs, String rt) {
             this.left_type = lt;
             this.left_size = ls;
             this.right_type = rt;
             this.right_size = rs;
         }
 
-        public SpanContext(String context) {
+
+        public SpanContext (String context) {
             this.context = context;
         }
 
+        public String getRightType() {
+            return this.right_type;
+        }
+
+        public String getLeftType() {
+            return this.left_type;
+        }
+
+        public Integer getLeftSize() {
+            return this.left_size;
+        }
+
+        public Integer getRightSize() {
+            return this.right_size;
+        }
+
         public Map raw() {
             Map meta = new LinkedHashMap();
             if (this.context == null) {
@@ -122,7 +143,8 @@
                 r.add(this.right_size);
                 map.put("right", r);
                 meta.put("context", map);
-            }else
+            }
+            else
                 meta.put("context", this.context);
             return meta;
         }
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusQueryProcessor.java b/src/main/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusQueryProcessor.java
index c3bd53f..03117dd 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusQueryProcessor.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusQueryProcessor.java
@@ -327,7 +327,11 @@
             // no 'term' child, but direct key specification: process here
             LinkedHashMap<String, Object> term = KoralObjectGenerator
                     .makeTerm();
+
             String key = node.getChild(0).getText();
+            TokenStream stream = parser.getTokenStream();
+            String kval = stream.getText(node.getChild(0).getSourceInterval());
+
             if (getNodeCat(node.getChild(0).getChild(0)).equals("regex")) {
                 isRegex = true;
                 term.put("type", "type:regex");
@@ -650,6 +654,7 @@
         ArrayList<Object> operands = (ArrayList<Object>) contains
                 .get("operands");
         operands.add(span);
+
         operands.add(queryObj);
         requestMap.put("query", contains);
         visited.add(node.getChild(0));
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/QuerySerializer.java b/src/main/java/de/ids_mannheim/korap/query/serialize/QuerySerializer.java
index 7f9166e..b7516fa 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/QuerySerializer.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/QuerySerializer.java
@@ -14,7 +14,7 @@
 /**
  * Main class for Koral, serializes queries from concrete QLs to
  * KoralQuery
- *
+ * 
  * @author Joachim Bingel (bingel@ids-mannheim.de),
  *         Michael Hanl (hanl@ids-mannheim.de),
  *         Eliza Margaretha (margaretha@ids-mannheim.de)
@@ -29,11 +29,10 @@
 
 
 
-
     static {
         qlProcessorAssignment = new HashMap<String, Class<? extends AbstractQueryProcessor>>();
-        qlProcessorAssignment
-                .put("poliqarpplus", PoliqarpPlusQueryProcessor.class);
+        qlProcessorAssignment.put("poliqarpplus",
+                PoliqarpPlusQueryProcessor.class);
         qlProcessorAssignment.put("cosmas2", Cosmas2QueryProcessor.class);
         qlProcessorAssignment.put("annis", AnnisQueryProcessor.class);
         qlProcessorAssignment.put("cql", CqlQueryProcessor.class);
@@ -52,16 +51,18 @@
     private org.slf4j.Logger log = LoggerFactory
             .getLogger(QuerySerializer.class);
 
-    public QuerySerializer() {
+
+    public QuerySerializer () {
         this.errors = new LinkedList<>();
         this.warnings = new LinkedList<>();
         this.messages = new LinkedList<>();
     }
 
+
     /**
      * @param args
      */
-    public static void main(String[] args) {
+    public static void main (String[] args) {
         /*
          * just for testing...
          */
@@ -74,7 +75,8 @@
             System.err
                     .println("Usage: QuerySerializer \"query\" queryLanguage");
             System.exit(1);
-        }else {
+        }
+        else {
             queries = new String[] { args[0] };
             ql = args[1];
         }
@@ -83,64 +85,86 @@
             try {
                 jg.run(q, ql);
                 System.out.println();
-            }catch (NullPointerException npe) {
+            }
+            catch (NullPointerException npe) {
                 npe.printStackTrace();
                 System.out.println("null\n");
-            }catch (IOException e) {
+            }
+            catch (IOException e) {
                 e.printStackTrace();
             }
         }
     }
 
+
     /**
      * Runs the QuerySerializer by initializing the relevant
      * AbstractSyntaxTree implementation (depending on specified query
      * language) and transforms and writes the tree's requestMap to
      * the specified output file.
-     *
-     * @param query         The query string
-     * @param queryLanguage The query language. As of 17 Dec 2014, this must be
-     *                      one of 'poliqarpplus', 'cosmas2', 'annis' or 'cql'.
+     * 
+     * @param query
+     *            The query string
+     * @param queryLanguage
+     *            The query language. As of 17 Dec 2014, this must be
+     *            one of 'poliqarpplus', 'cosmas2', 'annis' or 'cql'.
      * @throws IOException
      */
-    public void run(String query, String queryLanguage) throws IOException {
+    public void run (String query, String queryLanguage) throws IOException {
         if (queryLanguage.equalsIgnoreCase("poliqarp")) {
             ast = new PoliqarpPlusQueryProcessor(query);
-        }else if (queryLanguage.equalsIgnoreCase("cosmas2")) {
+        }
+        else if (queryLanguage.equalsIgnoreCase("cosmas2")) {
             ast = new Cosmas2QueryProcessor(query);
-        }else if (queryLanguage.equalsIgnoreCase("poliqarpplus")) {
+        }
+        else if (queryLanguage.equalsIgnoreCase("poliqarpplus")) {
             ast = new PoliqarpPlusQueryProcessor(query);
-        }else if (queryLanguage.equalsIgnoreCase("cql")) {
+        }
+        else if (queryLanguage.equalsIgnoreCase("cql")) {
             ast = new CqlQueryProcessor(query);
 		} else if (queryLanguage.equalsIgnoreCase("fcsql")) {
 			ast = new FCSQLQueryProcessor(query, "2.0");
         }else if (queryLanguage.equalsIgnoreCase("annis")) {
             ast = new AnnisQueryProcessor(query);
-        }else {
-            throw new IllegalArgumentException(
-                    queryLanguage + " is not a supported query language!");
+        }
+        else {
+            throw new IllegalArgumentException(queryLanguage
+                    + " is not a supported query language!");
         }
         toJSON();
     }
 
-    public QuerySerializer setQuery(String query, String ql, String version) {
+
+    public QuerySerializer setQuery (String query, String ql, String version) {
         ast = new DummyQueryProcessor();
         if (query == null || query.isEmpty()) {
             ast.addError(StatusCodes.NO_QUERY, "You did not specify a query!");
-        }else if (ql == null || ql.isEmpty()) {
+        }
+        else if (ql == null || ql.isEmpty()) {
             ast.addError(StatusCodes.NO_QUERY,
                     "You did not specify any query language!");
-        }else if (ql.equalsIgnoreCase("poliqarp")) {
+        }
+        else if (ql.equalsIgnoreCase("poliqarp")) {
             ast = new PoliqarpPlusQueryProcessor(query);
-        }else if (ql.equalsIgnoreCase("cosmas2")) {
+        }
+        else if (ql.equalsIgnoreCase("cosmas2")) {
             ast = new Cosmas2QueryProcessor(query);
-        }else if (ql.equalsIgnoreCase("poliqarpplus")) {
-            ast = new PoliqarpPlusQueryProcessor(query);
-        }else if (ql.equalsIgnoreCase("cql")) {
+        }
+        else if (ql.equalsIgnoreCase("poliqarpplus")) {
+            ast = new PoliqarpPlusQueryProcessor(query); 
+        }
+        else if (ql.equalsIgnoreCase("cql")) {
 			if (version == null) {
                 ast = new CqlQueryProcessor(query);
 			} else {
                 ast = new CqlQueryProcessor(query, version);
+            }
+        } else if (ql.equalsIgnoreCase("fcsql")) {
+			if (version == null) {
+				ast.addError(StatusCodes.MISSING_VERSION,
+						"SRU Version is missing!");
+			} else {
+				ast = new FCSQLQueryProcessor(query, version);
 			}
 		} else if (ql.equalsIgnoreCase("fcsql")) {
 			if (version == null) {
@@ -151,6 +175,7 @@
 			}
 		} else if (ql.equalsIgnoreCase("annis")) {
             ast = new AnnisQueryProcessor(query);
+
         }else {
 			ast.addError(StatusCodes.UNKNOWN_QUERY_LANGUAGE,
                     ql + " is not a supported query language!");
@@ -158,32 +183,38 @@
         return this;
     }
 
-    public QuerySerializer setQuery(String query, String ql) {
+
+    public QuerySerializer setQuery (String query, String ql) {
         return setQuery(query, ql, "");
     }
 
-    public void setVerbose(boolean verbose) {
+
+    public void setVerbose (boolean verbose) {
         AbstractQueryProcessor.verbose = verbose;
     }
 
-    public final String toJSON() {
+
+    public final String toJSON () {
         String ser;
         try {
             ser = mapper.writeValueAsString(raw());
             qllogger.info("Serialized query: " + ser);
-        }catch (JsonProcessingException e) {
+        }
+        catch (JsonProcessingException e) {
             return "";
         }
         return ser;
     }
 
-    public final Map build() {
+
+    public final Map build () {
         return raw();
     }
 
-    private Map raw() {
+
+    private Map raw () {
         if (ast != null) {
-            Map<String, Object> requestMap = ast.getRequestMap();
+            Map<String, Object> requestMap = new HashMap<>(ast.getRequestMap());
             Map meta = (Map) requestMap.get("meta");
             Map collection = (Map) requestMap.get("collection");
             List errors = (List) requestMap.get("errors");
@@ -191,9 +222,19 @@
             List messages = (List) requestMap.get("messages");
             collection = mergeCollection(collection, this.collection);
             requestMap.put("collection", collection);
+            
+            if (meta == null)
+                meta = new HashMap();
+            if (errors == null)
+                errors = new LinkedList();
+            if (warnings == null)
+                warnings = new LinkedList();
+            if (messages == null)
+                messages = new LinkedList();
+
             if (this.meta != null) {
-                this.meta.putAll(meta);
-                requestMap.put("meta", this.meta);
+                meta.putAll(this.meta);
+                requestMap.put("meta", meta);
             }
             if (this.errors != null && !this.errors.isEmpty()) {
                 errors.addAll(this.errors);
@@ -207,39 +248,43 @@
                 messages.addAll(this.messages);
                 requestMap.put("messages", messages);
             }
-
             return cleanup(requestMap);
         }
         return new HashMap<>();
     }
 
-    private Map<String, Object> cleanup(Map<String, Object> requestMap) {
+
+    private Map<String, Object> cleanup (Map<String, Object> requestMap) {
         Iterator<Map.Entry<String, Object>> set = requestMap.entrySet()
                 .iterator();
         while (set.hasNext()) {
             Map.Entry<String, Object> entry = set.next();
-            if (entry.getValue() instanceof List && ((List) entry.getValue())
-                    .isEmpty())
+            if (entry.getValue() instanceof List
+                    && ((List) entry.getValue()).isEmpty())
                 set.remove();
-            else if (entry.getValue() instanceof Map && ((Map) entry.getValue())
-                    .isEmpty())
+            else if (entry.getValue() instanceof Map
+                    && ((Map) entry.getValue()).isEmpty())
                 set.remove();
-            else if (entry.getValue() instanceof String && ((String) entry
-                    .getValue()).isEmpty())
+            else if (entry.getValue() instanceof String
+                    && ((String) entry.getValue()).isEmpty())
                 set.remove();
         }
         return requestMap;
     }
 
-    private Map<String, Object> mergeCollection(Map<String, Object> collection1,
-            Map<String, Object> collection2) {
+
+    private Map<String, Object> mergeCollection (
+            Map<String, Object> collection1, Map<String, Object> collection2) {
         if (collection1 == null || collection1.isEmpty()) {
             return collection2;
-        }else if (collection2 == null || collection2.isEmpty()) {
+        }
+        else if (collection2 == null || collection2.isEmpty()) {
             return collection1;
-        }else if (collection1.equals(collection2)) {
+        }
+        else if (collection1.equals(collection2)) {
             return collection1;
-        }else {
+        }
+        else {
             LinkedHashMap<String, Object> docGroup = KoralObjectGenerator
                     .makeDocGroup("and");
             ArrayList<Object> operands = (ArrayList<Object>) docGroup
@@ -250,8 +295,9 @@
         }
     }
 
+
     @Deprecated
-    public QuerySerializer addMeta(String cli, String cri, int cls, int crs,
+    public QuerySerializer addMeta (String cli, String cri, int cls, int crs,
             int num, int pageIndex) {
         MetaQueryBuilder meta = new MetaQueryBuilder();
         meta.setSpanContext(cls, cli, crs, cri);
@@ -261,17 +307,14 @@
         return this;
     }
 
-    public QuerySerializer setMeta(Map<String, Object> meta) {
+
+    public QuerySerializer setMeta (Map<String, Object> meta) {
         this.meta = meta;
         return this;
     }
 
-    public QuerySerializer setMeta(MetaQueryBuilder meta) {
-        this.meta = meta.raw();
-        return this;
-    }
 
-    public QuerySerializer setCollection(String collection) {
+    public QuerySerializer setCollection (String collection) {
         CollectionQueryProcessor tree = new CollectionQueryProcessor();
         tree.process(collection);
         Map<String, Object> collectionRequest = tree.getRequestMap();
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/QueryUtils.java b/src/main/java/de/ids_mannheim/korap/query/serialize/QueryUtils.java
index 6980b2e..47b5e09 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/QueryUtils.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/QueryUtils.java
@@ -14,7 +14,7 @@
  */
 public class QueryUtils {
 
-    public static SimpleEntry<String, Integer> checkUnbalancedPars(String q) {
+    public static SimpleEntry<String, Integer> checkUnbalancedPars (String q) {
         Map<Character, Character> brackets = new HashMap<Character, Character>();
         brackets.put('[', ']');
         brackets.put('{', '}');
@@ -31,8 +31,9 @@
             if (brackets.containsKey(q.charAt(i))) {
                 stack.push(q.charAt(i));
                 lastOpenBracket = i;
-            }else if (stack.empty() || (q.charAt(i) != brackets
-                    .get(stack.pop()))) {
+            }
+            else if (stack.empty()
+                    || (q.charAt(i) != brackets.get(stack.pop()))) {
                 return new SimpleEntry<String, Integer>(
                         "Parantheses/brackets unbalanced.", i);
             }
@@ -43,13 +44,15 @@
         return null;
     }
 
-    public static List<String> parseMorph(String stringTree) {
+
+    public static List<String> parseMorph (String stringTree) {
 
         ArrayList<String> morph = new ArrayList<String>();
         return morph;
     }
 
-    public static String buildCypherQuery(String cypher, String ctypel,
+
+    public static String buildCypherQuery (String cypher, String ctypel,
             String ctyper, int cl, int cr, int page, int limit) {
         // todo: implies that there is only one type allowed!
         String sctypel = "", sctyper = "";
@@ -100,7 +103,8 @@
         return buffer.toString();
     }
 
-    public static String buildDotQuery(long sid, String graphdb_id) {
+
+    public static String buildDotQuery (long sid, String graphdb_id) {
         StringBuffer b = new StringBuffer();
         b.append("<query>");
         b.append("<sentenceId>");
@@ -122,7 +126,8 @@
         return b.toString();
     }
 
-    public String buildaggreQuery(String query) {
+
+    public String buildaggreQuery (String query) {
         StringBuffer b = new StringBuffer();
         b.append("<query><cypher><![CDATA[");
         b.append(query);
@@ -151,9 +156,10 @@
         return b.toString();
     }
 
+
     @Deprecated
-    public static Map addParameters(Map request, int page, int num, String cli,
-            String cri, int cls, int crs, boolean cutoff) {
+    public static Map addParameters (Map request, int page, int num,
+            String cli, String cri, int cls, int crs, boolean cutoff) {
         Map ctx = new LinkedHashMap();
         List left = new ArrayList();
         left.add(cli);
@@ -172,14 +178,15 @@
         return request;
     }
 
+
     /**
      * Checks if value is a date
-     *
+     * 
      * @param value
      * @return
      */
 
-    public static boolean checkDateValidity(String value) {
+    public static boolean checkDateValidity (String value) {
         Pattern p = Pattern.compile("^[0-9]{4}(-([0-9]{2})(-([0-9]{2}))?)?$");
         Matcher m = p.matcher(value);
 
@@ -190,7 +197,8 @@
         if (month != null) {
             if (Integer.parseInt(month) > 12) {
                 return false;
-            }else if (day != null) {
+            }
+            else if (day != null) {
                 if (Integer.parseInt(day) > 31) {
                     return false;
                 }
@@ -199,7 +207,8 @@
         return true;
     }
 
-    public static String escapeRegexSpecialChars(String key) {
+
+    public static String escapeRegexSpecialChars (String key) {
         key.replace("\\", "\\\\");
         Pattern p = Pattern
                 .compile("\\.|\\^|\\$|\\||\\?|\\*|\\+|\\(|\\)|\\[|\\]|\\{|\\}");
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/util/KoralObjectGenerator.java b/src/main/java/de/ids_mannheim/korap/query/serialize/util/KoralObjectGenerator.java
index 20de50c..8381176 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/util/KoralObjectGenerator.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/util/KoralObjectGenerator.java
@@ -27,7 +27,9 @@
     public static LinkedHashMap<String, Object> makeSpan (String key) {
         LinkedHashMap<String, Object> span = new LinkedHashMap<String, Object>();
         span.put("@type", "koral:span");
-        span.put("key", key);
+        LinkedHashMap<String, Object> term = makeTerm();
+        term.put("key", key);
+        span.put("wrap", term);
         return span;
     }
 
@@ -334,4 +336,4 @@
         }
         return number;
     }
-}
\ No newline at end of file
+}
diff --git a/src/test/java/de/ids_mannheim/korap/query/serialize/CollectionQueryDuplicateTest.java b/src/test/java/de/ids_mannheim/korap/query/serialize/CollectionQueryDuplicateTest.java
index d3c1faa..f7c4dd1 100644
--- a/src/test/java/de/ids_mannheim/korap/query/serialize/CollectionQueryDuplicateTest.java
+++ b/src/test/java/de/ids_mannheim/korap/query/serialize/CollectionQueryDuplicateTest.java
@@ -2,10 +2,14 @@
 
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.Assert;
 import org.junit.Test;
 
 import java.io.IOException;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
 /**
  * @author hanl
  * @date 28/07/2015
@@ -13,20 +17,20 @@
 public class CollectionQueryDuplicateTest {
 
     @Test
-    public void testCollectionQueryDuplicateThrowsAssertionException() {
+    public void testCollectionQueryDuplicateThrowsAssertionException ()
+            throws IOException {
         QuerySerializer serializer = new QuerySerializer();
         serializer.setQuery("[base=Haus]", "poliqarp");
         serializer.setCollection("textClass=politik & corpusID=WPD");
         ObjectMapper m = new ObjectMapper();
-        try {
-            JsonNode first = m.readTree(serializer.toJSON());
-            JsonNode second = m.readTree(serializer.toJSON());
-
-            assert first.at("/collection").equals(second.at("/collection"));
-
-        }catch (IOException e) {
-            e.printStackTrace();
-        }
+        JsonNode first = m.readTree(serializer.toJSON());
+        assertNotNull(first);
+        assertEquals(first.at("/collection"), m.readTree(serializer.toJSON())
+                .at("/collection"));
+        assertEquals(first.at("/collection"), m.readTree(serializer.toJSON())
+                .at("/collection"));
+        assertEquals(first.at("/collection"), m.readTree(serializer.toJSON())
+                .at("/collection"));
     }
 
 }
diff --git a/src/test/java/de/ids_mannheim/korap/query/serialize/CollectionQueryProcessorTest.java b/src/test/java/de/ids_mannheim/korap/query/serialize/CollectionQueryProcessorTest.java
index 1a24352..0e91058 100644
--- a/src/test/java/de/ids_mannheim/korap/query/serialize/CollectionQueryProcessorTest.java
+++ b/src/test/java/de/ids_mannheim/korap/query/serialize/CollectionQueryProcessorTest.java
@@ -22,8 +22,9 @@
     ObjectMapper mapper = new ObjectMapper();
     JsonNode res;
 
+
     @Test
-    public void testContext() throws JsonProcessingException, IOException {
+    public void testContext () throws JsonProcessingException, IOException {
         collection = "textClass=politik";
         String contextString = "http://korap.ids-mannheim.de/ns/koral/0.3/context.jsonld";
         qs.setQuery(query, ql);
@@ -32,8 +33,9 @@
         assertEquals(contextString, res.get("@context").asText());
     }
 
+
     @Test
-    public void testSimple() throws JsonProcessingException, IOException {
+    public void testSimple () throws JsonProcessingException, IOException {
         collection = "textClass=politik";
         qs.setQuery(query, ql);
         qs.setCollection(collection);
@@ -53,9 +55,10 @@
         assertEquals("match:ne", res.at("/collection/match").asText());
     }
 
+
     @Test
-    public void testSpecialCharacters()
-            throws JsonProcessingException, IOException {
+    public void testSpecialCharacters () throws JsonProcessingException,
+            IOException {
         collection = "[base/n=alt]";
         qs.setQuery(query, ql);
         qs.setCollection(collection);
@@ -71,8 +74,9 @@
 
     ;
 
+
     @Test
-    public void testContains() throws JsonProcessingException, IOException {
+    public void testContains () throws JsonProcessingException, IOException {
         collection = "title~Mannheim";
         qs.setQuery(query, ql);
         qs.setCollection(collection);
@@ -101,8 +105,9 @@
         assertEquals("match:contains", res.at("/collection/match").asText());
     }
 
+
     @Test
-    public void testNotDate() throws JsonProcessingException, IOException {
+    public void testNotDate () throws JsonProcessingException, IOException {
         collection = "author=\"firefighter1974\"";
         qs.setQuery(query, ql);
         qs.setCollection(collection);
@@ -115,29 +120,29 @@
         assertEquals("", res.at("/warnings/0/0").asText());
     }
 
+
     @Test
-    public void testTwoConjuncts() throws JsonProcessingException, IOException {
+    public void testTwoConjuncts () throws JsonProcessingException, IOException {
         collection = "textClass=Sport & pubDate in 2014";
         qs.setQuery(query, ql);
         qs.setCollection(collection);
         res = mapper.readTree(qs.toJSON());
         assertEquals("koral:docGroup", res.at("/collection/@type").asText());
         assertEquals("operation:and", res.at("/collection/operation").asText());
-        assertEquals("koral:doc",
-                res.at("/collection/operands/0/@type").asText());
-        assertEquals("textClass",
-                res.at("/collection/operands/0/key").asText());
+        assertEquals("koral:doc", res.at("/collection/operands/0/@type")
+                .asText());
+        assertEquals("textClass", res.at("/collection/operands/0/key").asText());
         assertEquals("Sport", res.at("/collection/operands/0/value").asText());
-        assertEquals("match:eq",
-                res.at("/collection/operands/0/match").asText());
-        assertEquals("koral:doc",
-                res.at("/collection/operands/1/@type").asText());
+        assertEquals("match:eq", res.at("/collection/operands/0/match")
+                .asText());
+        assertEquals("koral:doc", res.at("/collection/operands/1/@type")
+                .asText());
         assertEquals("pubDate", res.at("/collection/operands/1/key").asText());
         assertEquals("2014", res.at("/collection/operands/1/value").asText());
-        assertEquals("type:date",
-                res.at("/collection/operands/1/type").asText());
-        assertEquals("match:eq",
-                res.at("/collection/operands/1/match").asText());
+        assertEquals("type:date", res.at("/collection/operands/1/type")
+                .asText());
+        assertEquals("match:eq", res.at("/collection/operands/1/match")
+                .asText());
 
         collection = "textClass=Sport & pubDate=2014";
         qs.setQuery(query, ql);
@@ -146,166 +151,165 @@
         res = mapper.readTree(qs.toJSON());
         assertEquals("koral:docGroup", res.at("/collection/@type").asText());
         assertEquals("operation:and", res.at("/collection/operation").asText());
-        assertEquals("koral:doc",
-                res.at("/collection/operands/0/@type").asText());
-        assertEquals("textClass",
-                res.at("/collection/operands/0/key").asText());
+        assertEquals("koral:doc", res.at("/collection/operands/0/@type")
+                .asText());
+        assertEquals("textClass", res.at("/collection/operands/0/key").asText());
         assertEquals("Sport", res.at("/collection/operands/0/value").asText());
-        assertEquals("match:eq",
-                res.at("/collection/operands/0/match").asText());
-        assertEquals("koral:doc",
-                res.at("/collection/operands/1/@type").asText());
+        assertEquals("match:eq", res.at("/collection/operands/0/match")
+                .asText());
+        assertEquals("koral:doc", res.at("/collection/operands/1/@type")
+                .asText());
         assertEquals("pubDate", res.at("/collection/operands/1/key").asText());
         assertEquals("2014", res.at("/collection/operands/1/value").asText());
-        assertEquals(true,
-                res.at("/collection/operands/1/type").isMissingNode());
-        assertEquals("match:eq",
-                res.at("/collection/operands/1/match").asText());
+        assertEquals(true, res.at("/collection/operands/1/type")
+                .isMissingNode());
+        assertEquals("match:eq", res.at("/collection/operands/1/match")
+                .asText());
         assertTrue(res.at("/warnings/0").isMissingNode());
         //        assertTrue(res.at("/warnings/0/0").asText().startsWith(
         //                "The collection query contains a value that looks like a date"));
     }
 
+
     @Test
-    public void testThreeConjuncts()
-            throws JsonProcessingException, IOException {
+    public void testThreeConjuncts () throws JsonProcessingException,
+            IOException {
         collection = "textClass=Sport & pubDate in 2014 & corpusId=WPD";
         qs.setQuery(query, ql);
         qs.setCollection(collection);
         res = mapper.readTree(qs.toJSON());
         assertEquals("koral:docGroup", res.at("/collection/@type").asText());
         assertEquals("operation:and", res.at("/collection/operation").asText());
-        assertEquals("koral:doc",
-                res.at("/collection/operands/0/@type").asText());
-        assertEquals("textClass",
-                res.at("/collection/operands/0/key").asText());
+        assertEquals("koral:doc", res.at("/collection/operands/0/@type")
+                .asText());
+        assertEquals("textClass", res.at("/collection/operands/0/key").asText());
         assertEquals("Sport", res.at("/collection/operands/0/value").asText());
-        assertEquals("match:eq",
-                res.at("/collection/operands/0/match").asText());
-        assertEquals("koral:docGroup",
-                res.at("/collection/operands/1/@type").asText());
-        assertEquals("operation:and",
-                res.at("/collection/operands/1/operation").asText());
+        assertEquals("match:eq", res.at("/collection/operands/0/match")
+                .asText());
+        assertEquals("koral:docGroup", res.at("/collection/operands/1/@type")
+                .asText());
+        assertEquals("operation:and", res
+                .at("/collection/operands/1/operation").asText());
         assertEquals("koral:doc",
                 res.at("/collection/operands/1/operands/0/@type").asText());
-        assertEquals("pubDate",
-                res.at("/collection/operands/1/operands/0/key").asText());
-        assertEquals("2014",
-                res.at("/collection/operands/1/operands/0/value").asText());
+        assertEquals("pubDate", res.at("/collection/operands/1/operands/0/key")
+                .asText());
+        assertEquals("2014", res.at("/collection/operands/1/operands/0/value")
+                .asText());
         assertEquals("type:date",
                 res.at("/collection/operands/1/operands/0/type").asText());
         assertEquals("match:eq",
                 res.at("/collection/operands/1/operands/0/match").asText());
         assertEquals("koral:doc",
                 res.at("/collection/operands/1/operands/1/@type").asText());
-        assertEquals("corpusId",
-                res.at("/collection/operands/1/operands/1/key").asText());
-        assertEquals("WPD",
-                res.at("/collection/operands/1/operands/1/value").asText());
+        assertEquals("corpusId", res
+                .at("/collection/operands/1/operands/1/key").asText());
+        assertEquals("WPD", res.at("/collection/operands/1/operands/1/value")
+                .asText());
         assertEquals("match:eq",
                 res.at("/collection/operands/1/operands/1/match").asText());
     }
 
+
     @Test
-    public void testTwoDisjuncts() throws JsonProcessingException, IOException {
+    public void testTwoDisjuncts () throws JsonProcessingException, IOException {
         collection = "textClass=Sport | pubDate in 2014";
         qs.setQuery(query, ql);
         qs.setCollection(collection);
         res = mapper.readTree(qs.toJSON());
         assertEquals("koral:docGroup", res.at("/collection/@type").asText());
         assertEquals("operation:or", res.at("/collection/operation").asText());
-        assertEquals("koral:doc",
-                res.at("/collection/operands/0/@type").asText());
-        assertEquals("textClass",
-                res.at("/collection/operands/0/key").asText());
+        assertEquals("koral:doc", res.at("/collection/operands/0/@type")
+                .asText());
+        assertEquals("textClass", res.at("/collection/operands/0/key").asText());
         assertEquals("Sport", res.at("/collection/operands/0/value").asText());
-        assertEquals("match:eq",
-                res.at("/collection/operands/0/match").asText());
-        assertEquals("koral:doc",
-                res.at("/collection/operands/1/@type").asText());
+        assertEquals("match:eq", res.at("/collection/operands/0/match")
+                .asText());
+        assertEquals("koral:doc", res.at("/collection/operands/1/@type")
+                .asText());
         assertEquals("pubDate", res.at("/collection/operands/1/key").asText());
         assertEquals("2014", res.at("/collection/operands/1/value").asText());
-        assertEquals("type:date",
-                res.at("/collection/operands/1/type").asText());
-        assertEquals("match:eq",
-                res.at("/collection/operands/1/match").asText());
+        assertEquals("type:date", res.at("/collection/operands/1/type")
+                .asText());
+        assertEquals("match:eq", res.at("/collection/operands/1/match")
+                .asText());
     }
 
+
     @Test
-    public void testThreeDisjuncts()
-            throws JsonProcessingException, IOException {
+    public void testThreeDisjuncts () throws JsonProcessingException,
+            IOException {
         collection = "textClass=Sport | pubDate in 2014 | corpusId=WPD";
         qs.setQuery(query, ql);
         qs.setCollection(collection);
         res = mapper.readTree(qs.toJSON());
         assertEquals("koral:docGroup", res.at("/collection/@type").asText());
         assertEquals("operation:or", res.at("/collection/operation").asText());
-        assertEquals("koral:doc",
-                res.at("/collection/operands/0/@type").asText());
-        assertEquals("textClass",
-                res.at("/collection/operands/0/key").asText());
+        assertEquals("koral:doc", res.at("/collection/operands/0/@type")
+                .asText());
+        assertEquals("textClass", res.at("/collection/operands/0/key").asText());
         assertEquals("Sport", res.at("/collection/operands/0/value").asText());
-        assertEquals("match:eq",
-                res.at("/collection/operands/0/match").asText());
-        assertEquals("koral:docGroup",
-                res.at("/collection/operands/1/@type").asText());
-        assertEquals("operation:or",
-                res.at("/collection/operands/1/operation").asText());
+        assertEquals("match:eq", res.at("/collection/operands/0/match")
+                .asText());
+        assertEquals("koral:docGroup", res.at("/collection/operands/1/@type")
+                .asText());
+        assertEquals("operation:or", res.at("/collection/operands/1/operation")
+                .asText());
         assertEquals("koral:doc",
                 res.at("/collection/operands/1/operands/0/@type").asText());
-        assertEquals("pubDate",
-                res.at("/collection/operands/1/operands/0/key").asText());
-        assertEquals("2014",
-                res.at("/collection/operands/1/operands/0/value").asText());
+        assertEquals("pubDate", res.at("/collection/operands/1/operands/0/key")
+                .asText());
+        assertEquals("2014", res.at("/collection/operands/1/operands/0/value")
+                .asText());
         assertEquals("type:date",
                 res.at("/collection/operands/1/operands/0/type").asText());
         assertEquals("match:eq",
                 res.at("/collection/operands/1/operands/0/match").asText());
         assertEquals("koral:doc",
                 res.at("/collection/operands/1/operands/1/@type").asText());
-        assertEquals("corpusId",
-                res.at("/collection/operands/1/operands/1/key").asText());
-        assertEquals("WPD",
-                res.at("/collection/operands/1/operands/1/value").asText());
+        assertEquals("corpusId", res
+                .at("/collection/operands/1/operands/1/key").asText());
+        assertEquals("WPD", res.at("/collection/operands/1/operands/1/value")
+                .asText());
         assertEquals("match:eq",
                 res.at("/collection/operands/1/operands/1/match").asText());
     }
 
+
     @Test
-    public void testMixed() throws JsonProcessingException, IOException {
+    public void testMixed () throws JsonProcessingException, IOException {
         collection = "textClass=Sport | (pubDate in 2014 & corpusId=WPD)";
         qs.setQuery(query, ql);
         qs.setCollection(collection);
         res = mapper.readTree(qs.toJSON());
         assertEquals("koral:docGroup", res.at("/collection/@type").asText());
         assertEquals("operation:or", res.at("/collection/operation").asText());
-        assertEquals("koral:doc",
-                res.at("/collection/operands/0/@type").asText());
-        assertEquals("textClass",
-                res.at("/collection/operands/0/key").asText());
+        assertEquals("koral:doc", res.at("/collection/operands/0/@type")
+                .asText());
+        assertEquals("textClass", res.at("/collection/operands/0/key").asText());
         assertEquals("Sport", res.at("/collection/operands/0/value").asText());
-        assertEquals("match:eq",
-                res.at("/collection/operands/0/match").asText());
-        assertEquals("koral:docGroup",
-                res.at("/collection/operands/1/@type").asText());
-        assertEquals("operation:and",
-                res.at("/collection/operands/1/operation").asText());
+        assertEquals("match:eq", res.at("/collection/operands/0/match")
+                .asText());
+        assertEquals("koral:docGroup", res.at("/collection/operands/1/@type")
+                .asText());
+        assertEquals("operation:and", res
+                .at("/collection/operands/1/operation").asText());
         assertEquals("koral:doc",
                 res.at("/collection/operands/1/operands/0/@type").asText());
-        assertEquals("pubDate",
-                res.at("/collection/operands/1/operands/0/key").asText());
-        assertEquals("2014",
-                res.at("/collection/operands/1/operands/0/value").asText());
+        assertEquals("pubDate", res.at("/collection/operands/1/operands/0/key")
+                .asText());
+        assertEquals("2014", res.at("/collection/operands/1/operands/0/value")
+                .asText());
         assertEquals("type:date",
                 res.at("/collection/operands/1/operands/0/type").asText());
         assertEquals("match:eq",
                 res.at("/collection/operands/1/operands/0/match").asText());
         assertEquals("koral:doc",
                 res.at("/collection/operands/1/operands/1/@type").asText());
-        assertEquals("corpusId",
-                res.at("/collection/operands/1/operands/1/key").asText());
-        assertEquals("WPD",
-                res.at("/collection/operands/1/operands/1/value").asText());
+        assertEquals("corpusId", res
+                .at("/collection/operands/1/operands/1/key").asText());
+        assertEquals("WPD", res.at("/collection/operands/1/operands/1/value")
+                .asText());
         assertEquals("match:eq",
                 res.at("/collection/operands/1/operands/1/match").asText());
 
@@ -315,33 +319,32 @@
         res = mapper.readTree(qs.toJSON());
         assertEquals("koral:docGroup", res.at("/collection/@type").asText());
         assertEquals("operation:or", res.at("/collection/operation").asText());
-        assertEquals("koral:doc",
-                res.at("/collection/operands/0/@type").asText());
-        assertEquals("textClass",
-                res.at("/collection/operands/0/key").asText());
+        assertEquals("koral:doc", res.at("/collection/operands/0/@type")
+                .asText());
+        assertEquals("textClass", res.at("/collection/operands/0/key").asText());
         assertEquals("Sport", res.at("/collection/operands/0/value").asText());
-        assertEquals("match:eq",
-                res.at("/collection/operands/0/match").asText());
-        assertEquals("koral:docGroup",
-                res.at("/collection/operands/1/@type").asText());
-        assertEquals("operation:and",
-                res.at("/collection/operands/1/operation").asText());
+        assertEquals("match:eq", res.at("/collection/operands/0/match")
+                .asText());
+        assertEquals("koral:docGroup", res.at("/collection/operands/1/@type")
+                .asText());
+        assertEquals("operation:and", res
+                .at("/collection/operands/1/operation").asText());
         assertEquals("koral:doc",
                 res.at("/collection/operands/1/operands/0/@type").asText());
-        assertEquals("pubDate",
-                res.at("/collection/operands/1/operands/0/key").asText());
-        assertEquals("2014",
-                res.at("/collection/operands/1/operands/0/value").asText());
+        assertEquals("pubDate", res.at("/collection/operands/1/operands/0/key")
+                .asText());
+        assertEquals("2014", res.at("/collection/operands/1/operands/0/value")
+                .asText());
         assertEquals("type:date",
                 res.at("/collection/operands/1/operands/0/type").asText());
         assertEquals("match:eq",
                 res.at("/collection/operands/1/operands/0/match").asText());
         assertEquals("koral:doc",
                 res.at("/collection/operands/1/operands/1/@type").asText());
-        assertEquals("corpusId",
-                res.at("/collection/operands/1/operands/1/key").asText());
-        assertEquals("WPD",
-                res.at("/collection/operands/1/operands/1/value").asText());
+        assertEquals("corpusId", res
+                .at("/collection/operands/1/operands/1/key").asText());
+        assertEquals("WPD", res.at("/collection/operands/1/operands/1/value")
+                .asText());
         assertEquals("match:eq",
                 res.at("/collection/operands/1/operands/1/match").asText());
 
@@ -351,16 +354,16 @@
         res = mapper.readTree(qs.toJSON());
         assertEquals("koral:docGroup", res.at("/collection/@type").asText());
         assertEquals("operation:and", res.at("/collection/operation").asText());
-        assertEquals("koral:docGroup",
-                res.at("/collection/operands/0/@type").asText());
-        assertEquals("operation:or",
-                res.at("/collection/operands/0/operation").asText());
+        assertEquals("koral:docGroup", res.at("/collection/operands/0/@type")
+                .asText());
+        assertEquals("operation:or", res.at("/collection/operands/0/operation")
+                .asText());
         assertEquals("koral:doc",
                 res.at("/collection/operands/0/operands/0/@type").asText());
         assertEquals("koral:doc",
                 res.at("/collection/operands/0/operands/1/@type").asText());
-        assertEquals("koral:doc",
-                res.at("/collection/operands/1/@type").asText());
+        assertEquals("koral:doc", res.at("/collection/operands/1/@type")
+                .asText());
 
         collection = "(textClass=Sport & pubDate in 2014) & corpusId=WPD";
         qs.setQuery(query, ql);
@@ -368,16 +371,16 @@
         res = mapper.readTree(qs.toJSON());
         assertEquals("koral:docGroup", res.at("/collection/@type").asText());
         assertEquals("operation:and", res.at("/collection/operation").asText());
-        assertEquals("koral:docGroup",
-                res.at("/collection/operands/0/@type").asText());
-        assertEquals("operation:and",
-                res.at("/collection/operands/0/operation").asText());
+        assertEquals("koral:docGroup", res.at("/collection/operands/0/@type")
+                .asText());
+        assertEquals("operation:and", res
+                .at("/collection/operands/0/operation").asText());
         assertEquals("koral:doc",
                 res.at("/collection/operands/0/operands/0/@type").asText());
         assertEquals("koral:doc",
                 res.at("/collection/operands/0/operands/1/@type").asText());
-        assertEquals("koral:doc",
-                res.at("/collection/operands/1/@type").asText());
+        assertEquals("koral:doc", res.at("/collection/operands/1/@type")
+                .asText());
 
         collection = "(textClass=Sport & textClass=ausland) | (corpusID=WPD & author=White)";
         qs.setQuery(query, ql);
@@ -385,30 +388,30 @@
         res = mapper.readTree(qs.toJSON());
         assertEquals("koral:docGroup", res.at("/collection/@type").asText());
         assertEquals("operation:or", res.at("/collection/operation").asText());
-        assertEquals("koral:docGroup",
-                res.at("/collection/operands/0/@type").asText());
-        assertEquals("operation:and",
-                res.at("/collection/operands/0/operation").asText());
-        assertEquals("koral:docGroup",
-                res.at("/collection/operands/1/@type").asText());
-        assertEquals("operation:and",
-                res.at("/collection/operands/1/operation").asText());
+        assertEquals("koral:docGroup", res.at("/collection/operands/0/@type")
+                .asText());
+        assertEquals("operation:and", res
+                .at("/collection/operands/0/operation").asText());
+        assertEquals("koral:docGroup", res.at("/collection/operands/1/@type")
+                .asText());
+        assertEquals("operation:and", res
+                .at("/collection/operands/1/operation").asText());
         assertEquals("koral:doc",
                 res.at("/collection/operands/0/operands/0/@type").asText());
-        assertEquals("Sport",
-                res.at("/collection/operands/0/operands/0/value").asText());
+        assertEquals("Sport", res.at("/collection/operands/0/operands/0/value")
+                .asText());
         assertEquals("koral:doc",
                 res.at("/collection/operands/0/operands/1/@type").asText());
         assertEquals("ausland",
                 res.at("/collection/operands/0/operands/1/value").asText());
         assertEquals("koral:doc",
                 res.at("/collection/operands/1/operands/0/@type").asText());
-        assertEquals("WPD",
-                res.at("/collection/operands/1/operands/0/value").asText());
+        assertEquals("WPD", res.at("/collection/operands/1/operands/0/value")
+                .asText());
         assertEquals("koral:doc",
                 res.at("/collection/operands/1/operands/1/@type").asText());
-        assertEquals("White",
-                res.at("/collection/operands/1/operands/1/value").asText());
+        assertEquals("White", res.at("/collection/operands/1/operands/1/value")
+                .asText());
 
         collection = "(textClass=Sport & textClass=ausland) | (corpusID=WPD & author=White & pubDate in 2000)";
         qs.setQuery(query, ql);
@@ -416,26 +419,26 @@
         res = mapper.readTree(qs.toJSON());
         assertEquals("koral:docGroup", res.at("/collection/@type").asText());
         assertEquals("operation:or", res.at("/collection/operation").asText());
-        assertEquals("koral:docGroup",
-                res.at("/collection/operands/0/@type").asText());
-        assertEquals("operation:and",
-                res.at("/collection/operands/0/operation").asText());
-        assertEquals("koral:docGroup",
-                res.at("/collection/operands/1/@type").asText());
-        assertEquals("operation:and",
-                res.at("/collection/operands/1/operation").asText());
+        assertEquals("koral:docGroup", res.at("/collection/operands/0/@type")
+                .asText());
+        assertEquals("operation:and", res
+                .at("/collection/operands/0/operation").asText());
+        assertEquals("koral:docGroup", res.at("/collection/operands/1/@type")
+                .asText());
+        assertEquals("operation:and", res
+                .at("/collection/operands/1/operation").asText());
         assertEquals("koral:doc",
                 res.at("/collection/operands/0/operands/0/@type").asText());
-        assertEquals("Sport",
-                res.at("/collection/operands/0/operands/0/value").asText());
+        assertEquals("Sport", res.at("/collection/operands/0/operands/0/value")
+                .asText());
         assertEquals("koral:doc",
                 res.at("/collection/operands/0/operands/1/@type").asText());
         assertEquals("ausland",
                 res.at("/collection/operands/0/operands/1/value").asText());
         assertEquals("koral:doc",
                 res.at("/collection/operands/1/operands/0/@type").asText());
-        assertEquals("WPD",
-                res.at("/collection/operands/1/operands/0/value").asText());
+        assertEquals("WPD", res.at("/collection/operands/1/operands/0/value")
+                .asText());
         assertEquals("koral:docGroup",
                 res.at("/collection/operands/1/operands/1/@type").asText());
         assertEquals("operation:and",
@@ -448,8 +451,9 @@
                         .asText());
     }
 
+
     @Test
-    public void testDateYear() throws JsonProcessingException, IOException {
+    public void testDateYear () throws JsonProcessingException, IOException {
         collection = "pubDate in 2000";
         qs.setQuery(query, ql);
         qs.setCollection(collection);
@@ -491,8 +495,9 @@
         assertEquals("match:leq", res.at("/collection/match").asText());
     }
 
+
     @Test
-    public void testDateMonthDay() throws JsonProcessingException, IOException {
+    public void testDateMonthDay () throws JsonProcessingException, IOException {
         collection = "pubDate in 2000-02";
         qs.setQuery(query, ql);
         qs.setCollection(collection);
@@ -534,8 +539,9 @@
         assertEquals("match:leq", res.at("/collection/match").asText());
     }
 
+
     @Test
-    public void testDateValidate() {
+    public void testDateValidate () {
         String fake_date = "fireStorm2014";
         String fake_date_2 = "2014-12Date";
         String date = "2015";
diff --git a/src/test/java/de/ids_mannheim/korap/query/serialize/Cosmas2QueryProcessorTest.java b/src/test/java/de/ids_mannheim/korap/query/serialize/Cosmas2QueryProcessorTest.java
index fa3adc8..9db30b9 100644
--- a/src/test/java/de/ids_mannheim/korap/query/serialize/Cosmas2QueryProcessorTest.java
+++ b/src/test/java/de/ids_mannheim/korap/query/serialize/Cosmas2QueryProcessorTest.java
@@ -18,7 +18,8 @@
  * Tests for JSON-LD serialization of Cosmas II queries.
  * 
  * @author Joachim Bingel (bingel@ids-mannheim.de)
- * @version 1.0
+ * @author Nils Diewald
+ * @version 1.1
  */
 public class Cosmas2QueryProcessorTest {
 
@@ -304,11 +305,17 @@
 
     @Test
     public void testOPORAND () throws JsonProcessingException, IOException {
+
+        // Query
         query = "(Sonne oder Mond) und scheint";
         qs.setQuery(query, "cosmas2");
         res = mapper.readTree(qs.toJSON());
         assertEquals("koral:group", res.at("/query/@type").asText());
         assertEquals("operation:sequence", res.at("/query/operation").asText());
+
+        assertEquals(false, res.at("/query/inOrder").isMissingNode());
+        assertEquals(false, res.at("/query/inOrder").asBoolean());
+
         assertEquals("cosmas:distance", res.at("/query/distances/0/@type")
                 .asText());
         assertEquals("t", res.at("/query/distances/0/key").asText());
@@ -317,6 +324,10 @@
         assertEquals("koral:group", res.at("/query/operands/0/@type").asText());
         assertEquals("operation:disjunction",
                 res.at("/query/operands/0/operation").asText());
+
+        assertEquals(false, res.at("/query/operands/0/inOrder").isMissingNode());
+        assertEquals(false, res.at("/query/operands/0/inOrder").asBoolean());
+
         assertEquals("Sonne", res.at("/query/operands/0/operands/0/wrap/key")
                 .asText());
         assertEquals("Mond", res.at("/query/operands/0/operands/1/wrap/key")
@@ -324,10 +335,15 @@
         assertEquals("koral:token", res.at("/query/operands/1/@type").asText());
         assertEquals("scheint", res.at("/query/operands/1/wrap/key").asText());
 
+        // Query
         query = "scheint und (Sonne oder Mond)";
         qs.setQuery(query, "cosmas2");
         res = mapper.readTree(qs.toJSON());
         assertEquals("koral:group", res.at("/query/@type").asText());
+
+        assertEquals(false, res.at("/query/inOrder").isMissingNode());
+        assertEquals(false, res.at("/query/inOrder").asBoolean());
+
         assertEquals("operation:sequence", res.at("/query/operation").asText());
         assertEquals("cosmas:distance", res.at("/query/distances/0/@type")
                 .asText());
@@ -339,16 +355,25 @@
         assertEquals("koral:group", res.at("/query/operands/1/@type").asText());
         assertEquals("operation:disjunction",
                 res.at("/query/operands/1/operation").asText());
+
+        assertEquals(false, res.at("/query/operands/1/inOrder").isMissingNode());
+        assertEquals(false, res.at("/query/operands/1/inOrder").asBoolean());
+
         assertEquals("Sonne", res.at("/query/operands/1/operands/0/wrap/key")
                 .asText());
         assertEquals("Mond", res.at("/query/operands/1/operands/1/wrap/key")
                 .asText());
 
+        // Query
         query = "Regen und scheint und (Sonne oder Mond)";
         qs.setQuery(query, "cosmas2");
         res = mapper.readTree(qs.toJSON());
         assertEquals("koral:group", res.at("/query/@type").asText());
         assertEquals("operation:sequence", res.at("/query/operation").asText());
+
+        assertEquals(false, res.at("/query/inOrder").isMissingNode());
+        assertEquals(false, res.at("/query/inOrder").asBoolean());
+
         assertEquals("cosmas:distance", res.at("/query/distances/0/@type")
                 .asText());
         assertEquals("t", res.at("/query/distances/0/key").asText());
@@ -356,8 +381,14 @@
         assertEquals(0, res.at("/query/distances/0/max").asInt());
         assertEquals("koral:token", res.at("/query/operands/0/@type").asText());
         assertEquals("Regen", res.at("/query/operands/0/wrap/key").asText());
-        assertEquals("koral:group", res.at("/query/@type").asText());
-        assertEquals("operation:sequence", res.at("/query/operation").asText());
+
+        assertEquals("koral:group", res.at("/query/operands/1/@type").asText());
+        assertEquals("operation:sequence", res
+                .at("/query/operands/1/operation").asText());
+
+        assertEquals(false, res.at("/query/operands/1/inOrder").isMissingNode());
+        assertEquals(false, res.at("/query/operands/1/inOrder").asBoolean());
+
         assertEquals("cosmas:distance",
                 res.at("/query/operands/1/distances/0/@type").asText());
         assertEquals("t", res.at("/query/operands/1/distances/0/key").asText());
@@ -367,6 +398,12 @@
                 .asText());
         assertEquals("koral:group", res
                 .at("/query/operands/1/operands/1/@type").asText());
+
+        assertEquals(false, res.at("/query/operands/1/operands/1/inOrder")
+                .isMissingNode());
+        assertEquals(false, res.at("/query/operands/1/operands/1/inOrder")
+                .asBoolean());
+
         assertEquals("operation:disjunction",
                 res.at("/query/operands/1/operands/1/operation").asText());
         assertEquals("Sonne",
@@ -685,7 +722,7 @@
                         .asText());
         assertEquals(
                 "s",
-                res.at("/query/operands/0/operands/0/operands/0/operands/0/key")
+                res.at("/query/operands/0/operands/0/operands/0/operands/0/wrap/key")
                         .asText());
         assertEquals("koral:group",
                 res.at("/query/operands/0/operands/0/operands/1/@type")
@@ -727,8 +764,9 @@
         assertEquals("koral:span",
                 res.at("/query/operands/0/operands/0/operands/0/@type")
                         .asText());
-        assertEquals("s", res.at("/query/operands/0/operands/0/operands/0/key")
-                .asText());
+        assertEquals("s",
+                res.at("/query/operands/0/operands/0/operands/0/wrap/key")
+                        .asText());
         assertEquals("koral:group", res
                 .at("/query/operands/0/operands/1/@type").asText());
         assertEquals("operation:class",
@@ -859,7 +897,7 @@
                         .asText());
         assertEquals(
                 "s",
-                res.at("/query/operands/0/operands/0/operands/0/operands/0/key")
+                res.at("/query/operands/0/operands/0/operands/0/operands/0/wrap/key")
                         .asText());
         assertEquals("koral:group",
                 res.at("/query/operands/0/operands/0/operands/1/@type")
@@ -1400,7 +1438,8 @@
                         .asText());
         assertEquals("koral:span", res.at("/query/operands/0/operands/0/@type")
                 .asText());
-        assertEquals("s", res.at("/query/operands/0/operands/0/key").asText());
+        assertEquals("s", res.at("/query/operands/0/operands/0/wrap/key")
+                .asText());
 
         query = "#BED(der Mann , +pe)";
         qs.setQuery(query, "cosmas2");
@@ -1424,8 +1463,9 @@
         assertEquals("koral:span",
                 res.at("/query/operands/0/operands/0/operands/0/@type")
                         .asText());
-        assertEquals("p", res.at("/query/operands/0/operands/0/operands/0/key")
-                .asText());
+        assertEquals("p",
+                res.at("/query/operands/0/operands/0/operands/0/wrap/key")
+                        .asText());
         assertEquals("koral:reference",
                 res.at("/query/operands/0/operands/1/@type").asText());
         assertEquals("operation:focus",
@@ -1477,8 +1517,9 @@
         assertEquals("koral:span",
                 res.at("/query/operands/0/operands/0/operands/0/@type")
                         .asText());
-        assertEquals("s", res.at("/query/operands/0/operands/0/operands/0/key")
-                .asText());
+        assertEquals("s",
+                res.at("/query/operands/0/operands/0/operands/0/wrap/key")
+                        .asText());
         assertEquals("koral:group",
                 res.at("/query/operands/0/operands/0/operands/1/@type")
                         .asText());
@@ -1512,8 +1553,9 @@
         assertEquals("koral:span",
                 res.at("/query/operands/0/operands/1/operands/0/@type")
                         .asText());
-        assertEquals("p", res.at("/query/operands/0/operands/1/operands/0/key")
-                .asText());
+        assertEquals("p",
+                res.at("/query/operands/0/operands/1/operands/0/wrap/key")
+                        .asText());
         assertEquals("koral:group",
                 res.at("/query/operands/0/operands/1/operands/1/@type")
                         .asText());
@@ -1566,7 +1608,8 @@
                         .asText());
         assertEquals("koral:span", res.at("/query/operands/0/operands/0/@type")
                 .asText());
-        assertEquals("s", res.at("/query/operands/0/operands/0/key").asText());
+        assertEquals("s", res.at("/query/operands/0/operands/0/wrap/key")
+                .asText());
 
         query = "der:sa,-pa";
         qs.setQuery(query, "cosmas2");
@@ -1588,8 +1631,9 @@
         assertEquals("koral:span",
                 res.at("/query/operands/0/operands/0/operands/0/@type")
                         .asText());
-        assertEquals("s", res.at("/query/operands/0/operands/0/operands/0/key")
-                .asText());
+        assertEquals("s",
+                res.at("/query/operands/0/operands/0/operands/0/wrap/key")
+                        .asText());
         assertEquals("koral:group",
                 res.at("/query/operands/0/operands/0/operands/1/@type")
                         .asText());
@@ -1614,8 +1658,9 @@
         assertEquals("koral:span",
                 res.at("/query/operands/0/operands/1/operands/0/@type")
                         .asText());
-        assertEquals("p", res.at("/query/operands/0/operands/1/operands/0/key")
-                .asText());
+        assertEquals("p",
+                res.at("/query/operands/0/operands/1/operands/0/wrap/key")
+                        .asText());
         assertEquals("koral:group",
                 res.at("/query/operands/0/operands/1/operands/1/@type")
                         .asText());
@@ -1650,8 +1695,9 @@
         assertEquals("koral:span",
                 res.at("/query/operands/0/operands/0/operands/0/@type")
                         .asText());
-        assertEquals("s", res.at("/query/operands/0/operands/0/operands/0/key")
-                .asText());
+        assertEquals("s",
+                res.at("/query/operands/0/operands/0/operands/0/wrap/key")
+                        .asText());
         assertEquals("koral:group",
                 res.at("/query/operands/0/operands/0/operands/1/@type")
                         .asText());
@@ -1702,7 +1748,7 @@
                         .asText());
         assertEquals(
                 "p",
-                res.at("/query/operands/0/operands/1/operands/0/operands/0/operands/0/key")
+                res.at("/query/operands/0/operands/1/operands/0/operands/0/operands/0/wrap/key")
                         .asText());
         assertEquals(
                 "koral:group",
@@ -1754,7 +1800,7 @@
                         .asText());
         assertEquals(
                 "t",
-                res.at("/query/operands/0/operands/1/operands/0/operands/1/operands/0/operands/0/key")
+                res.at("/query/operands/0/operands/1/operands/0/operands/1/operands/0/operands/0/wrap/key")
                         .asText());
         assertEquals(
                 "koral:reference",
diff --git a/src/test/java/de/ids_mannheim/korap/query/serialize/EmptyResultsTest.java b/src/test/java/de/ids_mannheim/korap/query/serialize/EmptyResultsTest.java
index fd2e64f..264ca67 100644
--- a/src/test/java/de/ids_mannheim/korap/query/serialize/EmptyResultsTest.java
+++ b/src/test/java/de/ids_mannheim/korap/query/serialize/EmptyResultsTest.java
@@ -5,6 +5,8 @@
 import org.junit.Assert;
 import org.junit.Test;
 
+import static org.junit.Assert.assertEquals;
+
 /**
  * @author hanl
  * @date 02/07/2015
@@ -13,32 +15,35 @@
 
     private static ObjectMapper mapper = new ObjectMapper();
 
+
     @Test
-    public void testEmptyQueryObject() {
+    public void testEmptyQueryObject () {
         QuerySerializer s = new QuerySerializer();
         s.setQuery("prox/unit=word/distance<=5", "cql");
         JsonNode node = mapper.valueToTree(s.build());
-        Assert.assertEquals(node.has("query"), false);
-        Assert.assertEquals(node.has("collection"), false);
+        assertEquals(node.has("query"), false);
+        assertEquals(node.has("collection"), false);
     }
 
+
     @Test
-    public void testEmptyCollectionObject() {
+    public void testEmptyCollectionObject () {
         QuerySerializer s = new QuerySerializer();
         s.setQuery("[base=Wort]", "poliqarp");
 
         JsonNode node = mapper.valueToTree(s.build());
-        Assert.assertEquals(node.has("query"), true);
-        Assert.assertEquals(node.has("collection"), false);
+        assertEquals(node.has("query"), true);
+        assertEquals(node.has("collection"), false);
     }
 
+
     @Test
-    public void testEmptyMetaObject() {
+    public void testEmptyMetaObject () {
         QuerySerializer s = new QuerySerializer();
         s.setQuery("[base=Wort]", "poliqarp");
 
         JsonNode node = mapper.valueToTree(s.build());
-        Assert.assertEquals(node.has("meta"), false);
+        assertEquals(node.has("meta"), false);
     }
 
 }
diff --git a/src/test/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusQueryProcessorTest.java b/src/test/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusQueryProcessorTest.java
index 171f1b3..221c0bc 100644
--- a/src/test/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusQueryProcessorTest.java
+++ b/src/test/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusQueryProcessorTest.java
@@ -148,6 +148,7 @@
         query = "z.B./x";
         qs.setQuery(query, "poliqarpplus");
         res = mapper.readTree(qs.toJSON());
+        System.out.println("QUERY IS  " + res);
         assertEquals("koral:token", res.at("/query/@type").asText());
         assertEquals("koral:term", res.at("/query/wrap/@type").asText());
         assertEquals(".*?z\\.B\\..*?", res.at("/query/wrap/key").asText());
@@ -159,12 +160,13 @@
         query = "\"a\\.\"";
         qs.setQuery(query, "poliqarpplus");
         res = mapper.readTree(qs.toJSON());
+        System.out.println("QUERY IS  " + res);
         assertEquals("koral:token", res.at("/query/@type").asText());
         assertEquals("koral:term", res.at("/query/wrap/@type").asText());
-        assertEquals("a\\.", res.at("/query/wrap/key").asText());
         assertEquals("type:regex", res.at("/query/wrap/type").asText());
         assertEquals("orth", res.at("/query/wrap/layer").asText());
         assertEquals("match:eq", res.at("/query/wrap/match").asText());
+        assertEquals("a\\.", res.at("/query/wrap/key").asText());
     }
 
 
@@ -1697,12 +1699,41 @@
         res = mapper.readTree(qs.toJSON());
         assertEquals("operation:position", res.at("/query/operation").asText());
         assertEquals("frames:isAround", res.at("/query/frames/0").asText());
-        assertEquals("s", res.at("/query/operands/0/key").asText());
+        assertEquals("s", res.at("/query/operands/0/wrap/key").asText());
         assertEquals("VVFIN", res.at("/query/operands/1/wrap/key").asText());
     }
 
 
     @Test
+    public void testSpanSerialization () throws JsonProcessingException,
+            IOException {
+
+        // Both constructs should be serialized identically
+        query = "contains(<s>, der)";
+        qs.setQuery(query, "poliqarpplus");
+        res = mapper.readTree(qs.toJSON());
+        assertEquals("koral:group", res.at("/query/@type").asText());
+        assertEquals("operation:position", res.at("/query/operation").asText());
+        assertEquals("frames:isAround", res.at("/query/frames/0").asText());
+        assertEquals(true, res.at("/query/frames/1").isMissingNode());
+        assertEquals("koral:span", res.at("/query/operands/0/@type").asText());
+        assertEquals("s", res.at("/query/operands/0/wrap/key").asText());
+        assertEquals("koral:token", res.at("/query/operands/1/@type").asText());
+
+        query = "der within s";
+        qs.setQuery(query, "poliqarpplus");
+        res = mapper.readTree(qs.toJSON());
+        assertEquals("koral:group", res.at("/query/@type").asText());
+        assertEquals("operation:position", res.at("/query/operation").asText());
+        assertEquals("frames:isAround", res.at("/query/frames/0").asText());
+        assertEquals(true, res.at("/query/frames/1").isMissingNode());
+        assertEquals("koral:span", res.at("/query/operands/0/@type").asText());
+        assertEquals("s", res.at("/query/operands/0/wrap/key").asText());
+        assertEquals("koral:token", res.at("/query/operands/1/@type").asText());
+    }
+
+
+    @Test
     public void testMeta () throws JsonProcessingException, IOException {
         query = "x meta textClass=Sport";
         qs.setQuery(query, "poliqarpplus");