removed all thrown errors from query serialisation workflow. all errors are reported via the field in the serialisation.
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/AbstractQueryProcessor.java b/src/main/java/de/ids_mannheim/korap/query/serialize/AbstractQueryProcessor.java
index 5e3ef4f..e6c4b4b 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/AbstractQueryProcessor.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/AbstractQueryProcessor.java
@@ -10,12 +10,9 @@
 import org.antlr.v4.runtime.tree.ParseTree;
 import org.slf4j.Logger;
 
-import de.ids_mannheim.korap.query.serialize.util.StatusCodes;
-import de.ids_mannheim.korap.query.serialize.util.QueryException;
-
 public abstract class AbstractQueryProcessor {
 	
-	public abstract void process(String query) throws QueryException;
+	public abstract void process(String query);
 	
 	Logger log;
 	/**
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/AnnisQueryProcessor.java b/src/main/java/de/ids_mannheim/korap/query/serialize/AnnisQueryProcessor.java
index 07fe43e..a823f9d 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/AnnisQueryProcessor.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/AnnisQueryProcessor.java
@@ -24,7 +24,6 @@
 import de.ids_mannheim.korap.query.parse.annis.AqlParser;
 import de.ids_mannheim.korap.query.serialize.util.Antlr4DescriptiveErrorListener;
 import de.ids_mannheim.korap.query.serialize.util.CqlfObjectGenerator;
-import de.ids_mannheim.korap.query.serialize.util.QueryException;
 
 /**
  * Map representation of ANNIS QL syntax tree as returned by ANTLR
@@ -88,16 +87,12 @@
 	 */
 	public AnnisQueryProcessor(String query) {
 		CqlfObjectGenerator.setQueryProcessor(this);
-		try {
-			process(query);
-		} catch (QueryException e) {
-			e.printStackTrace();
-		}
+		process(query);
 		System.out.println(">>> "+requestMap.get("query")+" <<<");
 	}
 
 	@Override
-	public void process(String query) throws QueryException {
+	public void process(String query) {
 		ParseTree tree = parseAnnisQuery(query);
 		if (this.parser != null) {
 			super.parser = this.parser;
@@ -713,7 +708,7 @@
 		}
 	}
 
-	private ParserRuleContext parseAnnisQuery (String query) throws QueryException {
+	private ParserRuleContext parseAnnisQuery (String query) {
 		Lexer lexer = new AqlLexer((CharStream)null);
 		ParserRuleContext tree = null;
 		Antlr4DescriptiveErrorListener errorListener = new Antlr4DescriptiveErrorListener(query);
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/Antlr3AbstractQueryProcessor.java b/src/main/java/de/ids_mannheim/korap/query/serialize/Antlr3AbstractQueryProcessor.java
index 4f0775f..4faa5e8 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/Antlr3AbstractQueryProcessor.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/Antlr3AbstractQueryProcessor.java
@@ -44,13 +44,13 @@
         return false;
     }
     
-    protected boolean hasDescendant(Tree node, String childCat) {
+    protected static boolean hasDescendantWithCat(Tree node, String childCat) {
         for (int i = 0; i < node.getChildCount(); i++) {
             Tree child = node.getChild(i);
             if (getNodeCat(child).equals(childCat)) {
                 return true;
             }
-            if (hasDescendant(child, childCat)) {
+            if (hasDescendantWithCat(child, childCat)) {
                 return true;
             }
         }
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/Antlr4AbstractQueryProcessor.java b/src/main/java/de/ids_mannheim/korap/query/serialize/Antlr4AbstractQueryProcessor.java
index 6873678..aecc928 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/Antlr4AbstractQueryProcessor.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/Antlr4AbstractQueryProcessor.java
@@ -47,13 +47,13 @@
         return false;
     }
 
-    protected boolean hasDescendant(ParseTree node, String childCat) {
+    protected boolean hasDescendantWithCat(ParseTree node, String childCat) {
         for (int i = 0; i < node.getChildCount(); i++) {
             ParseTree child = node.getChild(i);
             if (getNodeCat(child).equals(childCat)) {
                 return true;
             }
-            if (hasDescendant(child, childCat)) {
+            if (hasDescendantWithCat(child, childCat)) {
                 return true;
             }
         }
@@ -61,7 +61,7 @@
     }
     
 
-    protected static List<ParseTree> getChildren(ParseTree node) {
+    protected List<ParseTree> getChildren(ParseTree node) {
         ArrayList<ParseTree> children = new ArrayList<ParseTree>();
         for (int i = 0; i < node.getChildCount(); i++) {
                 children.add(node.getChild(i));
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/CollectionQueryBuilder2.java b/src/main/java/de/ids_mannheim/korap/query/serialize/CollectionQueryBuilder2.java
index 324a939..3d62b52 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/CollectionQueryBuilder2.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/CollectionQueryBuilder2.java
@@ -1,7 +1,6 @@
 package de.ids_mannheim.korap.query.serialize;
 
 import com.fasterxml.jackson.databind.JsonNode;
-import de.ids_mannheim.korap.query.serialize.util.QueryException;
 import de.ids_mannheim.korap.utils.JsonUtils;
 
 import java.io.IOException;
@@ -47,7 +46,7 @@
         return this;
     }
 
-    public CollectionQueryBuilder2 setQuery(String query) throws QueryException {
+    public CollectionQueryBuilder2 setQuery(String query) {
         CollectionQueryProcessor tree = new CollectionQueryProcessor();
         tree.process(query);
         this.groups = tree.getRequestMap();
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/CollectionQueryBuilder3.java b/src/main/java/de/ids_mannheim/korap/query/serialize/CollectionQueryBuilder3.java
index d87da4a..285f14b 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/CollectionQueryBuilder3.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/CollectionQueryBuilder3.java
@@ -1,6 +1,5 @@
 package de.ids_mannheim.korap.query.serialize;
 
-import de.ids_mannheim.korap.query.serialize.util.QueryException;
 import de.ids_mannheim.korap.utils.JsonUtils;
 
 import java.io.IOException;
@@ -63,7 +62,7 @@
         return this;
     }
 
-    public List getRequest() throws QueryException {
+    public List getRequest() {
         List list = new ArrayList();
         if (!this.rq.isEmpty())
             list.addAll(this.rq);
@@ -74,7 +73,7 @@
         return list;
     }
 
-    public String toJSON() throws QueryException {
+    public String toJSON() {
         return JsonUtils.toJSON(getRequest());
     }
 
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 26e86e3..0cd2768 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
@@ -5,7 +5,6 @@
 import de.ids_mannheim.korap.query.serialize.util.Antlr4DescriptiveErrorListener;
 import de.ids_mannheim.korap.query.serialize.util.CqlfObjectGenerator;
 import de.ids_mannheim.korap.query.serialize.util.StatusCodes;
-import de.ids_mannheim.korap.query.serialize.util.QueryException;
 
 import org.antlr.v4.runtime.*;
 import org.antlr.v4.runtime.tree.*;
@@ -51,13 +50,13 @@
     	CollectionQueryProcessor.verbose = verbose;
 	}
     
-    public CollectionQueryProcessor(String query) throws QueryException {
+    public CollectionQueryProcessor(String query) {
     	CqlfObjectGenerator.setQueryProcessor(this);
     	process(query);
 	}
 
 	@Override
-    public void process(String query) throws QueryException {
+    public void process(String query) {
         ParseTree tree = parseCollectionQuery(query);
         if (this.parser != null) {
             super.parser = this.parser;
@@ -66,7 +65,12 @@
         }
         log.info("Processing collection query: "+query);
         if (verbose) System.out.println(tree.toStringTree(parser));
-        processNode(tree);
+        if (tree != null) {
+			log.debug("ANTLR parse tree: "+tree.toStringTree(parser));
+			processNode(tree);
+		} else {
+			addError(StatusCodes.MALFORMED_QUERY, "Could not parse query >>> "+query+" <<<.");
+		}
     }
 
     private void processNode(ParseTree node) {
@@ -446,7 +450,7 @@
 		}
 	}
     
-    private ParserRuleContext parseCollectionQuery(String query) throws QueryException {
+    private ParserRuleContext parseCollectionQuery(String query) {
         Lexer lexer = new CollectionQueryLexer((CharStream) null);
         ParserRuleContext tree = null;
         Antlr4DescriptiveErrorListener errorListener = new Antlr4DescriptiveErrorListener(query);
@@ -474,9 +478,6 @@
         	System.err.println("ERROR: "+errorListener.generateFullErrorMsg());
             System.err.println("Parsing exception message: " + e);
         }
-        if (tree == null) {
-            throw new QueryException("Could not parse query. Make sure it is correct syntax.");
-        }
         // Return the generated tree
         return tree;
     }
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 f119b08..2ab4ddb 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
@@ -6,7 +6,6 @@
 import de.ids_mannheim.korap.query.serialize.util.CqlfObjectGenerator;
 import de.ids_mannheim.korap.query.serialize.util.ResourceMapper;
 import de.ids_mannheim.korap.query.serialize.util.StatusCodes;
-import de.ids_mannheim.korap.query.serialize.util.QueryException;
 
 import org.antlr.runtime.ANTLRStringStream;
 import org.antlr.runtime.RecognitionException;
@@ -77,7 +76,7 @@
 	/**
 	 * A list of node categories that can be sequenced (i.e. which can be in a sequence with any number of other nodes in this list)
 	 */
-	private final List<String> sequentiableCats = Arrays.asList(new String[]{"OPWF", "OPLEM", "OPMORPH", "OPBEG", "OPEND", "OPIN", "OPBED", "OPELEM", "OPOR", "OPAND"});
+	private final List<String> sequentiableNodeTypes = Arrays.asList(new String[]{"OPWF", "OPLEM", "OPMORPH", "OPBEG", "OPEND", "OPIN", "OPBED", "OPELEM", "OPOR", "OPAND"});
 	/**
 	 * Keeps track of sequenced nodes, i.e. nodes that implicitly govern  a sequence, as in (C2PQ (OPWF der) (OPWF Mann)).
 	 * This is necessary in order to know when to take the sequence off the object stack, as the sequence is introduced by the
@@ -97,7 +96,7 @@
 	 * @param parser The ANTLR parser instance that generated the parse tree
 	 * @throws QueryException
 	 */
-	public Cosmas2QueryProcessor(String query) throws QueryException {
+	public Cosmas2QueryProcessor(String query) {
 		CqlfObjectGenerator.setQueryProcessor(this);
 		this.query = query;
 		process(query);
@@ -105,7 +104,7 @@
 	}
 
 	@Override
-	public void process(String query) throws QueryException {
+	public void process(String query) {
 		Tree tree = null;
 		tree = parseCosmasQuery(query);
 		log.info("Processing CosmasII query: "+query);
@@ -115,8 +114,7 @@
 		}
 	}
 
-	private void processNode(Tree node) throws QueryException {
-
+	private void processNode(Tree node) {
 		// Top-down processing
 		if (visited.contains(node)) return;
 		else visited.add(node);
@@ -141,7 +139,7 @@
 
 		// Check for potential implicit sequences as in (C2PQ (OPWF der) (OPWF Mann)). The sequence is introduced
 		// by the first child if it (and its siblings) is sequentiable.
-		if (sequentiableCats.contains(nodeCat)) {
+		if (sequentiableNodeTypes.contains(nodeCat)) {
 			// for each node, check if parent has more than one child (-> could be implicit sequence)
 			Tree parent = node.getParent();
 			if (parent.getChildCount() > 1) {
@@ -149,7 +147,7 @@
 				if (node == parent.getChild(0)) {
 					nodeHasSequentiableSiblings = false;
 					for (int i = 1; i < parent.getChildCount(); i++) {
-						if (sequentiableCats.contains(getNodeCat(parent.getChild(i)))) {
+						if (sequentiableNodeTypes.contains(getNodeCat(parent.getChild(i)))) {
 							nodeHasSequentiableSiblings = true;
 							continue;
 						}
@@ -172,7 +170,6 @@
 				}
 			}
 		}
-
 		
 		if (nodeCat.equals("OPWF") || nodeCat.equals("OPLEM")) {
 			processOPWF_OPLEM(node);
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/CqlQueryProcessor.java b/src/main/java/de/ids_mannheim/korap/query/serialize/CqlQueryProcessor.java
index 5a06c1a..7e76964 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/CqlQueryProcessor.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/CqlQueryProcessor.java
@@ -1,6 +1,7 @@
 package de.ids_mannheim.korap.query.serialize;
 
-import de.ids_mannheim.korap.query.serialize.util.QueryException;
+import de.ids_mannheim.korap.query.serialize.util.StatusCodes;
+
 import org.z3950.zing.cql.*;
 
 import java.io.IOException;
@@ -31,15 +32,15 @@
     private String version;
     private boolean isCaseSensitive; // default true
     
-    public CqlQueryProcessor(String query) throws QueryException {
+    public CqlQueryProcessor(String query) {
         this(query, VERSION_1_2, true);
     }
 
-    public CqlQueryProcessor(String query, String version) throws QueryException {
+    public CqlQueryProcessor(String query, String version) {
         this(query, version, true);                
     }
 
-    public CqlQueryProcessor(String query, String version, boolean isCaseSensitive) throws QueryException {
+    public CqlQueryProcessor(String query, String version, boolean isCaseSensitive) {
         this.version = version;
         this.isCaseSensitive = isCaseSensitive;
         this.requestMap = new LinkedHashMap<>();
@@ -54,9 +55,9 @@
     }
 
     @Override
-    public void process(String query) throws QueryException {    	
+    public void process(String query) {    	
     	 if ((query == null) || query.isEmpty()) 
-             throw new QueryException(301, "SRU diagnostic 27: An empty query is unsupported.");
+             addError(StatusCodes.MALFORMED_QUERY, "SRU diagnostic 27: An empty query is unsupported.");
     	
         CQLNode cqlNode = parseQuerytoCQLNode(query);
         Map<String,Object> queryMap = parseCQLNode(cqlNode);
@@ -82,7 +83,7 @@
     	return map;
     }
     
-    private CQLNode parseQuerytoCQLNode(String query) throws QueryException {
+    private CQLNode parseQuerytoCQLNode(String query) {
         try {
             int compat = -1;
             switch (version) {
@@ -95,11 +96,12 @@
             return new CQLParser(compat).parse(query);
 
         } catch (CQLParseException | IOException e) {
-            throw new QueryException("Error parsing CQL");
+            addError(StatusCodes.MALFORMED_QUERY, "Error parsing CQL");
+            return null;
         }
     }
 
-    private Map<String,Object> parseCQLNode(CQLNode node) throws QueryException {    	
+    private Map<String,Object> parseCQLNode(CQLNode node) {    	
     	    	
         if (node instanceof CQLTermNode) {
             return parseTermNode((CQLTermNode) node);
@@ -108,16 +110,18 @@
         } else if (node instanceof CQLOrNode) {
             return parseOrNode((CQLOrNode) node);
         } else {
-            throw new QueryException(105, "SRU diagnostic 48: Only basic search including term-only " +
+            addError(StatusCodes.UNKNOWN_QUERY_ELEMENT, "SRU diagnostic 48: Only basic search including term-only " +
                     "and boolean (AND,OR) operator queries are currently supported.");
+            return new LinkedHashMap<String,Object>();
         }
     }
 
-    private Map<String,Object> parseTermNode(CQLTermNode node) throws QueryException {
+    private Map<String,Object> parseTermNode(CQLTermNode node) {
         checkTermNode(node);
         final String term = node.getTerm();
         if ((term == null) || term.isEmpty()) {
-            throw new QueryException(301, "SRU diagnostic 27: An empty term is unsupported.");
+            addError(StatusCodes.NO_QUERY, "SRU diagnostic 27: An empty term is unsupported.");
+            return new LinkedHashMap<String,Object>();
         } else if (term.contains(" ")) {
             return writeSequence(term);
         } else {
@@ -125,7 +129,7 @@
         }
     }
 
-    private Map<String,Object> parseAndNode(CQLAndNode node) throws QueryException {
+    private Map<String,Object> parseAndNode(CQLAndNode node) {
         checkBooleanModifier(node);
         
         Map<String, Object> map = new LinkedHashMap<String,Object>();
@@ -150,7 +154,7 @@
         return map;
     }
 
-    private Map<String,Object> parseOrNode(CQLOrNode node) throws QueryException {
+    private Map<String,Object> parseOrNode(CQLOrNode node) {
     	checkBooleanModifier(node);
     	
     	Map<String, Object> map = new LinkedHashMap<String,Object>();
@@ -196,20 +200,20 @@
     	return tokenMap;
     }
 
-    private void checkBooleanModifier(CQLBooleanNode node) throws QueryException {
+    private void checkBooleanModifier(CQLBooleanNode node) {
         List<Modifier> modifiers = node.getModifiers();
         if ((modifiers != null) && !modifiers.isEmpty()) {
             Modifier modifier = modifiers.get(0);
-            throw new QueryException(105, "SRU diagnostic 20: Relation modifier " +
+            addError(105, "SRU diagnostic 20: Relation modifier " +
                     modifier.toCQL() + " is not supported.");
         }
     }
 
-    private void checkTermNode(CQLTermNode node) throws QueryException {
+    private void checkTermNode(CQLTermNode node) {
         // only allow "cql.serverChoice" and "words" index
         if (!(INDEX_CQL_SERVERCHOICE.equals(node.getIndex()) ||
                 INDEX_WORDS.equals(node.getIndex()))) {
-            throw new QueryException(105, "SRU diagnostic 16: Index " + node.getIndex() + " is not supported.");
+            addError(105, "SRU diagnostic 16: Index " + node.getIndex() + " is not supported.");
         }
         // only allow "=" relation without any modifiers
         CQLRelation relation = node.getRelation();
@@ -217,13 +221,13 @@
         if (!(TERM_RELATION_CQL_1_1.equals(baseRel) ||
                 TERM_RELATION_CQL_1_2.equals(baseRel) ||
                 SUPPORTED_RELATION_EXACT.equals(baseRel))) {
-            throw new QueryException(105, "SRU diagnostic 19: Relation " +
+            addError(105, "SRU diagnostic 19: Relation " +
                     relation.getBase() + " is not supported.");
         }
         List<Modifier> modifiers = relation.getModifiers();
         if ((modifiers != null) && !modifiers.isEmpty()) {
             Modifier modifier = modifiers.get(0);
-            throw new QueryException(105, "SRU diagnostic 20: Relation modifier " +
+            addError(105, "SRU diagnostic 20: Relation modifier " +
                     modifier.getValue() + " is not supported.");
         }
     }
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/DummyQueryProcessor.java b/src/main/java/de/ids_mannheim/korap/query/serialize/DummyQueryProcessor.java
new file mode 100644
index 0000000..6c49737
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/DummyQueryProcessor.java
@@ -0,0 +1,16 @@
+package de.ids_mannheim.korap.query.serialize;
+
+/**
+ * This class serves as a dummy class for reporting errors when the query or query language as specified 
+ * in the {@link #QuerySerializer} are empty or erroneous. Without instatiating a class, errors/warnings cannot
+ * be reported.  
+ * @author bingel
+ *
+ */
+public final class DummyQueryProcessor extends AbstractQueryProcessor {
+
+	@Override
+	public void process(String query) {
+		// This is just a dummy class. Do nothing!		
+	}
+}
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 458e976..0da9e5c 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
@@ -5,7 +5,6 @@
 import de.ids_mannheim.korap.query.serialize.util.Antlr4DescriptiveErrorListener;
 import de.ids_mannheim.korap.query.serialize.util.CqlfObjectGenerator;
 import de.ids_mannheim.korap.query.serialize.util.StatusCodes;
-import de.ids_mannheim.korap.query.serialize.util.QueryException;
 
 import org.antlr.v4.runtime.*;
 import org.antlr.v4.runtime.tree.ParseTree;
@@ -34,14 +33,14 @@
 	 * @param query The syntax tree as returned by ANTLR
 	 * @throws QueryException
 	 */
-	public PoliqarpPlusQueryProcessor(String query) throws QueryException {
+	public PoliqarpPlusQueryProcessor(String query) {
 		CqlfObjectGenerator.setQueryProcessor(this);
 		process(query);
 		log.info(">>> " + requestMap.get("query") + " <<<");
 	}
 
 	@Override
-	public void process(String query) throws QueryException {
+	public void process(String query) {
 		ParseTree tree;
 		tree = parsePoliqarpQuery(query);
 		super.parser = this.parser;
@@ -49,6 +48,8 @@
 		if (tree != null) {
 			log.debug("ANTLR parse tree: "+tree.toStringTree(parser));
 			processNode(tree);
+		} else {
+			addError(StatusCodes.MALFORMED_QUERY, "Could not parse query >>> "+query+" <<<.");
 		}
 	}
 
@@ -62,7 +63,7 @@
 	 * @param node The currently processed node. The process(String query) method calls this method with the root.
 	 * @throws QueryException
 	 */
-	private void processNode(ParseTree node) throws QueryException {
+	private void processNode(ParseTree node) {
 		// Top-down processing
 		if (visited.contains(node)) return;
 		else visited.add(node);
@@ -748,7 +749,7 @@
 	}
 
 
-	private ParserRuleContext parsePoliqarpQuery(String query) throws QueryException {
+	private ParserRuleContext parsePoliqarpQuery(String query) {
 		Lexer lexer = new PoliqarpPlusLexer((CharStream) null);
 		ParserRuleContext tree = null;
 		Antlr4DescriptiveErrorListener errorListener = new Antlr4DescriptiveErrorListener(query);
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 e590957..9760854 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
@@ -4,7 +4,6 @@
 import com.fasterxml.jackson.databind.JsonMappingException;
 
 import de.ids_mannheim.korap.query.serialize.util.StatusCodes;
-import de.ids_mannheim.korap.query.serialize.util.QueryException;
 import de.ids_mannheim.korap.utils.JsonUtils;
 import de.ids_mannheim.korap.utils.KorAPLogger;
 
@@ -82,8 +81,6 @@
                 e.printStackTrace();
             } catch (IOException e) {
                 e.printStackTrace();
-            } catch (QueryException e) {
-                e.printStackTrace();
             }
         }
     }
@@ -99,56 +96,49 @@
      * @throws QueryException
      */
     public void run(String query, String queryLanguage, String outFile)
-            throws IOException, QueryException {
-        if (queryLanguage.equals("poliqarp")) {
+            throws IOException {
+        if (queryLanguage.equalsIgnoreCase("poliqarp")) {
             ast = new PoliqarpPlusQueryProcessor(query);
-        } else if (queryLanguage.toLowerCase().equals("cosmas2")) {
+        } else if (queryLanguage.equalsIgnoreCase("cosmas2")) {
             ast = new Cosmas2QueryProcessor(query);
-        } else if (queryLanguage.toLowerCase().equals("poliqarpplus")) {
+        } else if (queryLanguage.equalsIgnoreCase("poliqarpplus")) {
             ast = new PoliqarpPlusQueryProcessor(query);
-        } else if (queryLanguage.toLowerCase().equals("cql")) {
+        } else if (queryLanguage.equalsIgnoreCase("cql")) {
             ast = new CqlQueryProcessor(query);
-        } else if (queryLanguage.toLowerCase().equals("annis")) {
+        } else if (queryLanguage.equalsIgnoreCase("annis")) {
             ast = new AnnisQueryProcessor(query);
         } else {
-            throw new QueryException(queryLanguage + " is not a supported query language!");
+            throw new IllegalArgumentException(queryLanguage + " is not a supported query language!");
         }
         toJSON();
     }
 
-    public QuerySerializer setQuery(String query, String ql, String version)
-            throws QueryException {
-
-        if (query == null || query.isEmpty())
-            throw new QueryException(StatusCodes.NO_QUERY, "No Content!");
-
-        try {
-            if (ql.equalsIgnoreCase("poliqarp")) {
-                ast = new PoliqarpPlusQueryProcessor(query);
-            } else if (ql.equalsIgnoreCase("cosmas2")) {
-                ast = new Cosmas2QueryProcessor(query);
-            } 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("annis")) {
-                ast = new AnnisQueryProcessor(query);
-            } else {
-                throw new QueryException(ql + " is not a supported query language!");
-            }
-        } catch (QueryException e) {
-            throw e;
-        } catch (Exception e) {
-            e.printStackTrace();
-            throw new QueryException("UNKNOWN: Query could not be parsed (" + query + ")");
+    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()){
+            ast.addError(StatusCodes.NO_QUERY, "You did not specify any query language!");
+        } else if (ql.equalsIgnoreCase("poliqarp")) {
+            ast = new PoliqarpPlusQueryProcessor(query);
+        } else if (ql.equalsIgnoreCase("cosmas2")) {
+            ast = new Cosmas2QueryProcessor(query);
+        } 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("annis")) {
+            ast = new AnnisQueryProcessor(query);
+        } else {
+        	ast.addError(StatusCodes.UNKNOWN_QL, ql + " is not a supported query language!");
         }
         return this;
     }
 
-    public QuerySerializer setQuery(String query, String ql) throws QueryException {
+    public QuerySerializer setQuery(String query, String ql) {
         return setQuery(query, ql, "");
     }
 
@@ -228,7 +218,7 @@
         return this;
     }
 
-    public QuerySerializer setCollection(String collection) throws QueryException {
+    public QuerySerializer setCollection(String collection) {
         CollectionQueryProcessor tree = new CollectionQueryProcessor();
         Map collectionRequest = tree.getRequestMap();
         tree.process(collection);
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/TreeTemplate.java b/src/main/java/de/ids_mannheim/korap/query/serialize/TreeTemplate.java
index 1c20f96..9c74336 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/TreeTemplate.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/TreeTemplate.java
@@ -3,92 +3,63 @@
 import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
 
 import org.antlr.v4.runtime.ANTLRInputStream;
 import org.antlr.v4.runtime.BailErrorStrategy;
 import org.antlr.v4.runtime.CharStream;
 import org.antlr.v4.runtime.CommonTokenStream;
 import org.antlr.v4.runtime.Lexer;
-import org.antlr.v4.runtime.Parser;
 import org.antlr.v4.runtime.ParserRuleContext;
 import org.antlr.v4.runtime.tree.ParseTree;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
+//TODO replace AqlLexer with lexer for your Antlr4 grammar!
 import de.ids_mannheim.korap.query.parse.annis.AqlLexer;
+//TODO replace AqlParser with parser for your Antlr4 grammar!
 import de.ids_mannheim.korap.query.parse.annis.AqlParser;
-import de.ids_mannheim.korap.query.serialize.util.QueryException;
+import de.ids_mannheim.korap.query.serialize.util.CqlfObjectGenerator;
+import de.ids_mannheim.korap.query.serialize.util.StatusCodes;
 
 /**
  * Map representation of syntax tree as returned by ANTLR
- * @author bingel
+ * @author Joachim Bingel (bingel@ids-mannheim.de)
  *
  */
 public class TreeTemplate extends Antlr4AbstractQueryProcessor {
-	/**
-	 * Keeps track of open node categories
-	 */
-	LinkedList<String> openNodeCats = new LinkedList<String>();
-	/**
-	 * Flag that indicates whether token fields or meta fields are currently being processed
-	 */
-	boolean inMeta = false;
-	/**
-	 * Parser object deriving the ANTLR parse tree.
-	 */
-	static Parser qlParser;
-	/**
-	 * Keeps track of all visited nodes in a tree
-	 */
-	List<ParseTree> visited = new ArrayList<ParseTree>();
-	/**
-	 * Keeps track of active object.
-	 */
-	LinkedList<LinkedHashMap<String,Object>> objectStack = new LinkedList<LinkedHashMap<String,Object>>();
-	/**
-	 * Marks the currently active token in order to know where to add flags (might already have been taken away from token stack).
-	 */
-	LinkedHashMap<String,Object> curToken = new LinkedHashMap<String,Object>();
-
-	private LinkedList<ArrayList<ArrayList<Object>>> distributedOperandsLists = new LinkedList<ArrayList<ArrayList<Object>>>();
-	
-	/**
-	 * Keeps track of how many objects there are to pop after every recursion of {@link #processNode(ParseTree)}
-	 */
-	LinkedList<Integer> objectsToPop = new LinkedList<Integer>();
-	Integer stackedObjects = 0;
-	public static boolean verbose = false;
-	
+	private static Logger log = LoggerFactory.getLogger(TreeTemplate.class);
 	/**
 	 * 
 	 * @param tree The syntax tree as returned by ANTLR
 	 * @param parser The ANTLR parser instance that generated the parse tree
 	 */
 	public TreeTemplate(String query) {
-		try {
-			process(query);
-		} catch (QueryException e) {
-			e.printStackTrace();
+		CqlfObjectGenerator.setQueryProcessor(this);
+		process(query);
+	}
+
+	@Override
+	public void process(String query) {
+		ParseTree tree = parseQuery(query);
+		super.parser = this.parser;
+		if (tree != null) {
+			log.debug("ANTLR parse tree: "+tree.toStringTree(parser));
+			processNode(tree);
+		} else {
+			addError(StatusCodes.MALFORMED_QUERY, "Could not parse query >>> "+query+" <<<.");
 		}
 	}
-	
-	@Override
-	public void process(String query) throws QueryException {
-		ParseTree tree = parseQuery(query);
-		System.out.println("Processing Annis QL");
-		processNode(tree);
-	}
-	
+
 	private void processNode(ParseTree node) {
 		// Top-down processing
 		if (visited.contains(node)) return;
 		else visited.add(node);
-		
+
 		String nodeCat = getNodeCat(node);
 		openNodeCats.push(nodeCat);
-		
+
 		stackedObjects = 0;
-		
+
 		if (verbose) {
 			System.err.println(" "+objectStack);
 			System.out.println(openNodeCats);
@@ -103,7 +74,7 @@
 		 */
 
 		objectsToPop.push(stackedObjects);
-		
+
 		/*
 		 ****************************************************************
 		 **************************************************************** 
@@ -115,76 +86,69 @@
 			ParseTree child = node.getChild(i);
 			processNode(child);
 		}
-				
-		
+
+
 		/*
 		 **************************************************************
 		 * Stuff that happens after processing the children of a node *
 		 **************************************************************
 		 */
-		
-		
+
+
 		for (int i=0; i<objectsToPop.pop(); i++) {
 			objectStack.pop();
 		}
-		
+
 
 		openNodeCats.pop();
-		
+
 	}
 
 	@SuppressWarnings("unused")
 	private void putIntoSuperObject(LinkedHashMap<String, Object> object) {
 		putIntoSuperObject(object, 0);
 	}
-	
+
 	@SuppressWarnings({ "unchecked" })
 	private void putIntoSuperObject(LinkedHashMap<String, Object> object, int objStackPosition) {
-		if (distributedOperandsLists.size()>0) {
-			ArrayList<ArrayList<Object>> distributedOperands = distributedOperandsLists.pop();
-			for (ArrayList<Object> operands : distributedOperands) {
-				operands.add(object);
-			}
-		} else if (objectStack.size()>objStackPosition) {
+		if (objectStack.size()>objStackPosition) {
 			ArrayList<Object> topObjectOperands = (ArrayList<Object>) objectStack.get(objStackPosition).get("operands");
 			topObjectOperands.add(0, object);
-			
+
 		} else {
 			requestMap.put("query", object);
 		}
 	}
-	
-	private static ParserRuleContext parseQuery (String q) throws QueryException {
-		Lexer qlLexer = new AqlLexer((CharStream)null);
-	    ParserRuleContext tree = null;
-	    // Like p. 111
-	    try {
 
-	      // Tokenize input data
-	      ANTLRInputStream input = new ANTLRInputStream(q);
-	      qlLexer.setInputStream(input);
-	      CommonTokenStream tokens = new CommonTokenStream(qlLexer);
-	      qlParser = new AqlParser(tokens);
+	private ParserRuleContext parseQuery (String q) {
+		//TODO replace AqlLexer with lexer for your Antlr4 grammar!
+		Lexer qlLexer = new AqlLexer((CharStream)null); 
+		ParserRuleContext tree = null;
+		// Like p. 111
+		try {
+			// Tokenize input data
+			ANTLRInputStream input = new ANTLRInputStream(q);
+			qlLexer.setInputStream(input);
+			CommonTokenStream tokens = new CommonTokenStream(qlLexer);
+			//TODO replace AqlParser with parser for your Antlr4 grammar!
+			parser = new AqlParser(tokens);
 
-	      // Don't throw out erroneous stuff
-	      qlParser.setErrorHandler(new BailErrorStrategy());
-	      qlParser.removeErrorListeners();
+			// Don't throw out erroneous stuff
+			parser.setErrorHandler(new BailErrorStrategy());
+			parser.removeErrorListeners();
 
-	      // Get starting rule from parser
-	      Method startRule = AqlParser.class.getMethod("start"); 
-	      tree = (ParserRuleContext) startRule.invoke(qlParser, (Object[])null);
-	    }
+			// Get starting rule from parser
+			//TODO replace AqlParser with parser for your Antlr4 grammar!
+			Method startRule = AqlParser.class.getMethod("start"); 
+			tree = (ParserRuleContext) startRule.invoke(parser, (Object[])null);
+		}
 
-	    // Some things went wrong ...
-	    catch (Exception e) {
-	      System.err.println( e.getMessage() );
-	    }
-	    
-	    if (tree == null) {
-	    	throw new QueryException("Could not parse query. Make sure it is correct QL syntax.");
-	    }
+		// Some things went wrong ...
+		catch (Exception e) {
+			System.err.println( e.getMessage() );
+		}
 
-	    // Return the generated tree
-	    return tree;
-	  }
+		// Return the generated tree
+		return tree;
+	}
 }
\ No newline at end of file
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/util/CqlfObjectGenerator.java b/src/main/java/de/ids_mannheim/korap/query/serialize/util/CqlfObjectGenerator.java
index b03959d..abc4511 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/util/CqlfObjectGenerator.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/util/CqlfObjectGenerator.java
@@ -269,4 +269,4 @@
 		}
 		return number;
 	}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/util/QueryException.java b/src/main/java/de/ids_mannheim/korap/query/serialize/util/QueryException.java
deleted file mode 100644
index ff63f79..0000000
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/util/QueryException.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package de.ids_mannheim.korap.query.serialize.util;
-
-public class QueryException extends Exception {
-	
-  int errorCode;
-  
-  public QueryException() {
-      super();
-  }
-
-  public QueryException(String message) {
-      super(message);
-  }
-
-  public QueryException(String message, Throwable cause) {
-      super(message, cause);
-  };
-
-  public QueryException(Throwable cause) {
-      super(cause);
-  };  
-  
-  public QueryException(int code, String message) {	  
-	  super(message);
-	  setErrorCode(code);      
-  }
-
-  public int getErrorCode() {
-	return errorCode;
-  }
-
-  public void setErrorCode(int errorCode) {
-	this.errorCode = errorCode;
-  }
-
-};
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/util/StatusCodes.java b/src/main/java/de/ids_mannheim/korap/query/serialize/util/StatusCodes.java
index 6fe6afd..ffdedf0 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/util/StatusCodes.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/util/StatusCodes.java
@@ -7,5 +7,6 @@
 	public final static int UNDEFINED_CLASS_REFERENCE = 304;
 	public final static int INCOMPATIBLE_OPERATOR_AND_OPERAND = 305;
 	public final static int UNKNOWN_QUERY_ELEMENT = 306;
+	public static final int UNKNOWN_QL = 307;
 	public final static int UNKNOWN_QUERY_ERROR = 399;
 }