Updated KoralSpan. Added KoralException.

Change-Id: I0676a3ee17d8ecd2fb03b5a2044c11ac34e7a3b6
diff --git a/pom.xml b/pom.xml
index fb782a4..f575129 100644
--- a/pom.xml
+++ b/pom.xml
@@ -20,6 +20,11 @@
     <dependency>
       <groupId>org.antlr</groupId>
       <artifactId>antlr4-runtime</artifactId>
+      <version>4.2</version>
+    </dependency>
+    <dependency>
+      <groupId>org.antlr</groupId>
+      <artifactId>antlr4-runtime</artifactId>
       <version>4.5.1</version>
     </dependency>
     <dependency>
diff --git a/src/main/java/de/ids_mannheim/korap/query/object/KoralContext.java b/src/main/java/de/ids_mannheim/korap/query/object/KoralContext.java
new file mode 100644
index 0000000..ca789a9
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/query/object/KoralContext.java
@@ -0,0 +1,18 @@
+package de.ids_mannheim.korap.query.object;
+
+public enum KoralContext {
+	SENTENCE("s"), PARAGRAPH("p"), TEXT("t");
+	
+	private final String key;
+	public static final String FOUNDRY ="base";
+	public static final String LAYER="s"; // surface
+	
+	KoralContext(String key){
+		this.key = key;
+	}
+
+	public String getKey() {
+		return key;
+	}
+
+}
diff --git a/src/main/java/de/ids_mannheim/korap/query/object/KoralGroup.java b/src/main/java/de/ids_mannheim/korap/query/object/KoralGroup.java
index 61a2e04..090ecbc 100644
--- a/src/main/java/de/ids_mannheim/korap/query/object/KoralGroup.java
+++ b/src/main/java/de/ids_mannheim/korap/query/object/KoralGroup.java
@@ -1,4 +1,4 @@
-package de.ids_mannheim.korap.query.elements;
+package de.ids_mannheim.korap.query.object;
 
 import java.util.ArrayList;
 import java.util.LinkedHashMap;
@@ -6,19 +6,22 @@
 import java.util.Map;
 
 import de.ids_mannheim.korap.query.serialize.MapBuilder;
+import de.ids_mannheim.korap.query.object.KoralObject;
+import de.ids_mannheim.korap.query.object.KoralOperation;
+import de.ids_mannheim.korap.query.object.KoralType;
 
 /**
  * @author margaretha
  * 
  */
-public class KoralGroup implements Element {
+public class KoralGroup implements KoralObject {
 
     private static final KoralType type = KoralType.GROUP;
 
-    private KoralOperation operation;;
+    private KoralOperation operation;
 
     private boolean inOrder = false;
-    private List<Object> operands;
+    private List<KoralObject> operands;
     private List<Distance> distances;
     private List<Frame> frames;
 
@@ -34,13 +37,13 @@
         this.inOrder = inOrder;
     }
 
-    public List<Object> getOperands() {
-        return operands;
-    }
-
-    public void setOperands(List<Object> operands) {
-        this.operands = operands;
-    }
+    public List<KoralObject> getOperands() {
+		return operands;
+	}
+    
+    public void setOperands(List<KoralObject> operands) {
+		this.operands = operands;
+	}
 
     public List<Distance> getDistances() {
         return distances;
@@ -49,14 +52,14 @@
     public void setDistances(List<Distance> distances) {
         this.distances = distances;
     }
-
+    
     public List<Frame> getFrames() {
-        return frames;
-    }
+		return frames;
+	}
 
-    public void setFrames(List<Frame> frames) {
-        this.frames = frames;
-    }
+	public void setFrames(List<Frame> frames) {
+		this.frames = frames;
+	}
 
     @Override
     public Map<String, Object> buildMap() {
@@ -73,14 +76,6 @@
             map.put("distances", distanceList);
         }
 
-        if (getFrames() != null) {
-            List<String> frameList = new ArrayList<String>();
-            for (Frame f : getFrames()) {
-                frameList.add(f.toString());
-            }
-            map.put("frames", frameList);
-        }
-
         List<Map<String, Object>> operandList = new ArrayList<Map<String, Object>>();
         for (Object o : getOperands()) {
             operandList.add(MapBuilder.buildQueryMap(o));
@@ -89,27 +84,24 @@
         return map;
     }
 
-    public enum Frame {
-        SUCCEDS("succeds"), SUCCEDS_DIRECTLY("succeedsDirectly"), OVERLAPS_RIGHT(
-                "overlapsRight"), ALIGNS_RIGHT("alignsRight"), IS_WITHIN(
-                "isWithin"), STARTS_WITH("startsWith"), MATCHES("matches"), ALIGNS_LEFT(
-                "alignsLeft"), IS_AROUND("isAround"), ENDS_WITH("endsWith"), OVERLAPS_LEFT(
-                "overlapsLeft"), PRECEDES_DIRECTLY("precedesDirectly"), PRECEDES(
-                "precedes");
-
-        String value;
-
-        Frame (String value) {
-            this.value = value;
-        }
-
-        @Override
-        public String toString() {
-            return "frames:" + value;
-        };
-    }
-
-    public class Distance implements Element {
+    public enum Frame{
+		SUCCEDS("succeeds"), SUCCEDS_DIRECTLY("succeedsDirectly"), OVERLAPS_RIGHT("overlapsRight"), 
+		ALIGNS_RIGHT("alignsRight"), IS_WITHIN("isWithin"), STARTS_WITH("startsWith"), 
+		MATCHES("matches"), ALIGNS_LEFT("alignsLeft"), IS_AROUND("isAround"), ENDS_WITH("endsWith"),
+		OVERLAPS_LEFT("overlapsLeft"), PRECEEDS_DIRECTLY("precedesDirectly"), PRECEDES("precedes");
+		
+		private String value;
+		Frame(String value) {
+			this.value = value;
+		}
+		
+		@Override
+		public String toString() {
+			return "frame:"+value;
+		}
+	}
+    
+    public class Distance implements KoralObject {
 
         private final KoralType type = KoralType.DISTANCE;
         private String key;
diff --git a/src/main/java/de/ids_mannheim/korap/query/object/KoralMatchOperator.java b/src/main/java/de/ids_mannheim/korap/query/object/KoralMatchOperator.java
index 2963744..2a25202 100644
--- a/src/main/java/de/ids_mannheim/korap/query/object/KoralMatchOperator.java
+++ b/src/main/java/de/ids_mannheim/korap/query/object/KoralMatchOperator.java
@@ -1,11 +1,11 @@
-package de.ids_mannheim.korap.query.elements;
+package de.ids_mannheim.korap.query.object;
 
-public enum MatchOperator {
+public enum KoralMatchOperator {
     EQUALS("eq"), NOT_EQUALS("ne");
 
     String value;
 
-    MatchOperator (String value) {
+    KoralMatchOperator (String value) {
         this.value = value;
     }
 
diff --git a/src/main/java/de/ids_mannheim/korap/query/object/KoralObject.java b/src/main/java/de/ids_mannheim/korap/query/object/KoralObject.java
index 73f580a..21fcf67 100644
--- a/src/main/java/de/ids_mannheim/korap/query/object/KoralObject.java
+++ b/src/main/java/de/ids_mannheim/korap/query/object/KoralObject.java
@@ -1,4 +1,4 @@
-package de.ids_mannheim.korap.query.elements;
+package de.ids_mannheim.korap.query.object;
 
 import java.util.Map;
 
@@ -6,7 +6,7 @@
  * @author margaretha
  * 
  */
-public interface Element {
+public interface KoralObject {
 
     public Map<String, Object> buildMap();
 }
diff --git a/src/main/java/de/ids_mannheim/korap/query/object/KoralOperation.java b/src/main/java/de/ids_mannheim/korap/query/object/KoralOperation.java
index 21fa833..972bfd3 100644
--- a/src/main/java/de/ids_mannheim/korap/query/object/KoralOperation.java
+++ b/src/main/java/de/ids_mannheim/korap/query/object/KoralOperation.java
@@ -1,4 +1,4 @@
-package de.ids_mannheim.korap.query.elements;
+package de.ids_mannheim.korap.query.object;
 
 /**
  * @author margaretha
diff --git a/src/main/java/de/ids_mannheim/korap/query/object/KoralRelation.java b/src/main/java/de/ids_mannheim/korap/query/object/KoralRelation.java
index f1bfa91..84a1ff8 100644
--- a/src/main/java/de/ids_mannheim/korap/query/object/KoralRelation.java
+++ b/src/main/java/de/ids_mannheim/korap/query/object/KoralRelation.java
@@ -1,4 +1,4 @@
-package de.ids_mannheim.korap.query.elements;
+package de.ids_mannheim.korap.query.object;
 
 /**
  * @author margaretha
diff --git a/src/main/java/de/ids_mannheim/korap/query/object/KoralSpan.java b/src/main/java/de/ids_mannheim/korap/query/object/KoralSpan.java
index bec50a3..4310bb9 100644
--- a/src/main/java/de/ids_mannheim/korap/query/object/KoralSpan.java
+++ b/src/main/java/de/ids_mannheim/korap/query/object/KoralSpan.java
@@ -1,75 +1,62 @@
-package de.ids_mannheim.korap.query.elements;
+package de.ids_mannheim.korap.query.object;
 
 import java.util.LinkedHashMap;
-import java.util.List;
 import java.util.Map;
 
-public class KoralSpan implements Element {
+import de.ids_mannheim.korap.query.serialize.util.KoralException;
+import de.ids_mannheim.korap.query.serialize.util.StatusCodes;
 
-    private static final KoralType koralType = KoralType.SPAN;
+/**
+ * @author margaretha
+ *
+ */
+public class KoralSpan implements KoralObject{
+	
+	private static final KoralType type = KoralType.SPAN;
+	private final KoralObject wrappedObject;
+	private KoralObject attribute;
+	
+	public KoralSpan(KoralTerm term) throws KoralException {
+		if (term == null){
+			throw new KoralException(StatusCodes.MALFORMED_QUERY, "KoralSpan must not wrap null.");
+		}
+		this.wrappedObject = term;
+	}
+	
+	public KoralSpan(KoralTermGroup termGroup) throws KoralException {
+		if (termGroup == null){
+			throw new KoralException(StatusCodes.MALFORMED_QUERY,"KoralSpan must not wrap null.");
+		}
+		this.wrappedObject = termGroup;
+	}
 
-    private String key;
-    private String foundry;
-    private String layer;
-    private String matchOperator;
-    private List<KoralTerm> attr;
-
-    public KoralSpan (String key, String foundry, String layer,
-            MatchOperator operator) {
-        this.key = key;
-        this.foundry = foundry;
-        this.layer = layer;
-        this.matchOperator = operator.toString();
-    }
-
-    public String getKey() {
-        return key;
-    }
-
-    public void setKey(String key) {
-        this.key = key;
-    }
-
-    public String getFoundry() {
-        return foundry;
-    }
-
-    public void setFoundry(String foundry) {
-        this.foundry = foundry;
-    }
-
-    public String getLayer() {
-        return layer;
-    }
-
-    public void setLayer(String layer) {
-        this.layer = layer;
-    }
-
-    public String getMatchOperator() {
-        return matchOperator;
-    }
-
-    public void setMatchOperator(String matchOperator) {
-        this.matchOperator = matchOperator;
-    }
-
-    public List<KoralTerm> getAttr() {
-        return attr;
-    }
-
-    public void setAttr(List<KoralTerm> attr) {
-        this.attr = attr;
-    }
-
-    @Override
-    public Map<String, Object> buildMap() {
-        Map<String, Object> map = new LinkedHashMap<String, Object>();
-        map.put("@type", koralType.toString());
-        map.put("key", getKey());
-        map.put("foundry", getFoundry());
-        map.put("layer", getLayer());
-        map.put("match", getMatchOperator());
-        return map;
-    }
+	public KoralObject getWrappedObject() {
+		return wrappedObject;
+	}
+	
+	public KoralObject getAttribute() {
+		return attribute;
+	}
+	
+	public void setAttribute(KoralTerm attribute) {
+		this.attribute = attribute;
+	}
+	
+	public void setAttribute(KoralTermGroup attributes) {
+		this.attribute = attributes;
+	}
+	
+	@Override
+	public Map<String, Object> buildMap() {
+		Map<String, Object> map = new LinkedHashMap<String, Object>();
+        map.put("@type", type.toString());
+        if (wrappedObject == null){
+        	throw new NullPointerException("KoralSpan does not have a wrapped object.");
+        }
+        map.put("wrap", wrappedObject.buildMap());
+        if(attribute != null){
+        	map.put("wrap", attribute.buildMap());
+        }
+		return map;
+	}
 }
diff --git a/src/main/java/de/ids_mannheim/korap/query/object/KoralTerm.java b/src/main/java/de/ids_mannheim/korap/query/object/KoralTerm.java
index 1960799..f9f60cd 100644
--- a/src/main/java/de/ids_mannheim/korap/query/object/KoralTerm.java
+++ b/src/main/java/de/ids_mannheim/korap/query/object/KoralTerm.java
@@ -1,41 +1,58 @@
-package de.ids_mannheim.korap.query.elements;
+package de.ids_mannheim.korap.query.object;
 
 import java.util.LinkedHashMap;
 import java.util.Map;
 
+import de.ids_mannheim.korap.query.serialize.util.KoralException;
+import de.ids_mannheim.korap.query.serialize.util.StatusCodes;
+import de.ids_mannheim.korap.query.object.KoralMatchOperator;
+import de.ids_mannheim.korap.query.object.KoralType;
+
 /**
  * @author margaretha
  * 
  */
-public class KoralTerm implements Element {
-
-    public enum KoralTermType {
-        STRING("type:string"), REGEX("type:regex"), WILDCARD("type:wildcard"), PUNCT(
-                "type:punct");
-
-        String value;
-
-        KoralTermType (String value) {
-            this.value = value;
-        }
-
-        @Override
-        public String toString() {
-            return value;
-        }
-    }
+public class KoralTerm implements KoralObject {
 
     private static final KoralType koralType = KoralType.TERM;
-
+  
+    private final String key;
+    private String value;
     private String layer;
     private String foundry;
-    private String operator;
-    private String key;
+    private KoralMatchOperator operator; // match
+    
     private KoralTermType type;
+    
     private boolean caseSensitive = true;
-    private boolean invalid = false;
 
-    public String getLayer() {
+    public KoralTerm(String key) throws KoralException {
+    	if (key == null){
+    		throw new KoralException(StatusCodes.MALFORMED_QUERY, 
+    				"KoralTerm key cannot be null.");
+    	}
+    	this.key = key;
+    }
+    
+    public KoralTerm(KoralContext context) throws KoralException {
+    	if (context.getKey() == null){
+    		throw new KoralException(StatusCodes.MALFORMED_QUERY, 
+    				"KoralTerm key cannot be null.");
+    	}
+    	this.key = context.getKey();
+    	this.foundry = KoralContext.FOUNDRY;
+    	this.layer = KoralContext.LAYER;
+	}
+    
+    public String getValue() {
+		return value;
+	}
+    
+    public void setValue(String value) {
+		this.value = value;
+	}
+    
+	public String getLayer() {
         return layer;
     }
 
@@ -51,22 +68,18 @@
         this.foundry = foundry;
     }
 
-    public String getOperator() {
-        return operator;
-    }
-
-    public void setOperator(String operator) {
-        this.operator = operator;
-    }
+    public KoralMatchOperator getOperator() {
+		return operator;
+	}
+    
+    public void setOperator(KoralMatchOperator operator) {
+		this.operator = operator;
+	}
 
     public String getKey() {
         return key;
     }
 
-    public void setKey(String key) {
-        this.key = key;
-    }
-
     public KoralTermType getType() {
         return type;
     }
@@ -83,14 +96,6 @@
         this.caseSensitive = isCaseSensitive;
     }
 
-    public boolean isInvalid() {
-        return invalid;
-    }
-
-    public void setInvalid(boolean invalid) {
-        this.invalid = invalid;
-    }
-
     @Override
     public Map<String, Object> buildMap() {
         Map<String, Object> map = new LinkedHashMap<String, Object>();
@@ -98,12 +103,36 @@
         if (!isCaseSensitive()) {
             map.put("caseInsensitive", "true");
         }
+        
         map.put("key", getKey());
+        if (value != null){
+        	map.put("value", getValue());
+        }
         map.put("foundry", getFoundry());
         map.put("layer", getLayer());
-        map.put("type", getType().toString());
-        map.put("match", getOperator());
-
+        if (type != null){
+        	map.put("type", getType().toString());
+        }
+		if (operator !=null){
+			map.put("match", getOperator().toString());
+		}
         return map;
     }
+
+    public enum KoralTermType {
+        STRING("type:string"), REGEX("type:regex"), WILDCARD("type:wildcard"), PUNCT(
+                "type:punct");
+
+        String value;
+
+        KoralTermType (String value) {
+            this.value = value;
+        }
+
+        @Override
+        public String toString() {
+            return value;
+        }
+    }
+
 }
diff --git a/src/main/java/de/ids_mannheim/korap/query/object/KoralTermGroup.java b/src/main/java/de/ids_mannheim/korap/query/object/KoralTermGroup.java
index 96dac7f..e9eba9f 100644
--- a/src/main/java/de/ids_mannheim/korap/query/object/KoralTermGroup.java
+++ b/src/main/java/de/ids_mannheim/korap/query/object/KoralTermGroup.java
@@ -1,4 +1,4 @@
-package de.ids_mannheim.korap.query.elements;
+package de.ids_mannheim.korap.query.object;
 
 import java.util.ArrayList;
 import java.util.LinkedHashMap;
@@ -14,7 +14,7 @@
  * @author margaretha
  * 
  */
-public class KoralTermGroup implements Element {
+public class KoralTermGroup implements KoralObject {
 
     private static final KoralType type = KoralType.TERMGROUP;
 
diff --git a/src/main/java/de/ids_mannheim/korap/query/object/KoralToken.java b/src/main/java/de/ids_mannheim/korap/query/object/KoralToken.java
index 6f3f221..06a39ce 100644
--- a/src/main/java/de/ids_mannheim/korap/query/object/KoralToken.java
+++ b/src/main/java/de/ids_mannheim/korap/query/object/KoralToken.java
@@ -1,34 +1,36 @@
-package de.ids_mannheim.korap.query.elements;
+package de.ids_mannheim.korap.query.object;
 
 import java.util.LinkedHashMap;
 import java.util.Map;
 
+import de.ids_mannheim.korap.query.object.KoralObject;
+import de.ids_mannheim.korap.query.object.KoralType;
+
 /**
  * @author margaretha
  * 
  */
-public class KoralToken implements Element {
+public class KoralToken implements KoralObject {
 
     private final static KoralType type = KoralType.TOKEN;
-    private Element child;
+    private KoralObject wrappedObject;
 
-    public KoralToken (Element child) {
-        this.child = child;
+    public KoralToken (KoralObject wrappedObject) {
+        this.wrappedObject = wrappedObject;
     }
 
-    public Element getChild() {
-        return child;
-    }
-
-    public void setChild(Element child) {
-        this.child = child;
-    }
+    public KoralObject getWrappedObject() {
+		return wrappedObject;
+	}
+    public void setWrappedObject(KoralObject wrappedObject) {
+		this.wrappedObject = wrappedObject;
+	}
 
     @Override
     public Map<String, Object> buildMap() {
         Map<String, Object> map = new LinkedHashMap<String, Object>();
         map.put("@type", type.toString());
-        map.put("wrap", child.buildMap());
+        map.put("wrap", wrappedObject.buildMap());
         return map;
     }
 }
diff --git a/src/main/java/de/ids_mannheim/korap/query/object/KoralType.java b/src/main/java/de/ids_mannheim/korap/query/object/KoralType.java
index ed5c456..df7608f 100644
--- a/src/main/java/de/ids_mannheim/korap/query/object/KoralType.java
+++ b/src/main/java/de/ids_mannheim/korap/query/object/KoralType.java
@@ -1,4 +1,4 @@
-package de.ids_mannheim.korap.query.elements;
+package de.ids_mannheim.korap.query.object;
 
 /**
  * @author margaretha
diff --git a/src/main/java/de/ids_mannheim/korap/query/parse/fcsql/ExpressionParser.java b/src/main/java/de/ids_mannheim/korap/query/parse/fcsql/ExpressionParser.java
index 82b75de..d62f4a7 100644
--- a/src/main/java/de/ids_mannheim/korap/query/parse/fcsql/ExpressionParser.java
+++ b/src/main/java/de/ids_mannheim/korap/query/parse/fcsql/ExpressionParser.java
@@ -4,14 +4,15 @@
 import java.util.List;
 import java.util.Set;
 
-import de.ids_mannheim.korap.query.elements.KoralRelation;
-import de.ids_mannheim.korap.query.elements.KoralTerm;
-import de.ids_mannheim.korap.query.elements.KoralTerm.KoralTermType;
-import de.ids_mannheim.korap.query.elements.KoralTermGroup;
-import de.ids_mannheim.korap.query.elements.KoralToken;
-import de.ids_mannheim.korap.query.elements.MatchOperator;
-import de.ids_mannheim.korap.query.serialize.FCSQLQueryProcessor;
+import de.ids_mannheim.korap.query.serialize.util.KoralException;
 import de.ids_mannheim.korap.query.serialize.util.StatusCodes;
+import de.ids_mannheim.korap.query.object.KoralMatchOperator;
+import de.ids_mannheim.korap.query.object.KoralObject;
+import de.ids_mannheim.korap.query.object.KoralRelation;
+import de.ids_mannheim.korap.query.object.KoralTerm;
+import de.ids_mannheim.korap.query.object.KoralTermGroup;
+import de.ids_mannheim.korap.query.object.KoralToken;
+import de.ids_mannheim.korap.query.object.KoralTerm.KoralTermType;
 import eu.clarin.sru.server.fcs.parser.Expression;
 import eu.clarin.sru.server.fcs.parser.ExpressionAnd;
 import eu.clarin.sru.server.fcs.parser.ExpressionNot;
@@ -36,18 +37,12 @@
             .asList(new String[] { FOUNDRY_CNX, FOUNDRY_OPENNLP, FOUNDRY_TT,
                     FOUNDRY_MATE, FOUNDRY_XIP });
 
-    private FCSQLQueryProcessor processor;
-
-    public ExpressionParser (FCSQLQueryProcessor processor) {
-        this.processor = processor;
-    }
-
-    public Object parseExpression(QueryNode queryNode) {
+    public KoralObject parseExpression(QueryNode queryNode) throws KoralException {
         return parseExpression(queryNode, false, true);
     }
 
-    public Object parseExpression(QueryNode queryNode, boolean isNot,
-            boolean isToken) {
+    public KoralObject parseExpression(QueryNode queryNode, boolean isNot,
+            boolean isToken) throws KoralException {
 
         if (queryNode instanceof Expression) {
             return parseSimpleExpression((Expression) queryNode, isNot, isToken);
@@ -81,20 +76,19 @@
         // for distance query, using empty token
         // }
         else {
-            processor.addError(StatusCodes.QUERY_TOO_COMPLEX,
+            throw new KoralException(StatusCodes.QUERY_TOO_COMPLEX,
                     "FCS diagnostic 11: Query is too complex.");
-            return null;
         }
     }
 
-    private Object parseBooleanExpression(List<QueryNode> operands,
-            KoralRelation relation) {
+    private KoralObject parseBooleanExpression(List<QueryNode> operands,
+            KoralRelation relation) throws KoralException {
         KoralTermGroup termGroup = new KoralTermGroup(this, relation, operands);
         return new KoralToken(termGroup);
     }
 
-    private Object parseSimpleExpression(Expression expression, boolean isNot,
-            boolean isToken) {
+    private KoralObject parseSimpleExpression(Expression expression, boolean isNot,
+            boolean isToken) throws KoralException {
         KoralTerm koralTerm = parseTerm(expression, isNot);
         if (isToken) {
             return new KoralToken(koralTerm);
@@ -104,10 +98,10 @@
         }
     }
 
-    public KoralTerm parseTerm(Expression expression, boolean isNot) {
-        KoralTerm koralTerm = new KoralTerm();
+    public KoralTerm parseTerm(Expression expression, boolean isNot) throws KoralException {
+    	KoralTerm koralTerm = null;
+    	koralTerm = new KoralTerm(expression.getRegexValue());
         koralTerm.setType(KoralTermType.REGEX);
-        koralTerm.setKey(expression.getRegexValue());
         parseLayerIdentifier(koralTerm, expression.getLayerIdentifier());
         parseQualifier(koralTerm, expression.getLayerQualifier());
         parseOperator(koralTerm, expression.getOperator(), isNot);
@@ -115,12 +109,11 @@
         return koralTerm;
     }
 
-    private void parseLayerIdentifier(KoralTerm koralTerm, String identifier) {
+    private void parseLayerIdentifier(KoralTerm koralTerm, String identifier) throws KoralException {
         String layer = null;
         if (identifier == null) {
-            processor.addError(StatusCodes.MALFORMED_QUERY,
+            throw new KoralException(StatusCodes.MALFORMED_QUERY,
                     "FCS diagnostic 10: Layer identifier is missing.");
-            koralTerm.setInvalid(true);
         }
         else if (identifier.equals("text")) {
             layer = "orth";
@@ -132,19 +125,17 @@
             layer = "l";
         }
         else {
-            processor.addError(StatusCodes.UNKNOWN_QUERY_ELEMENT,
+            throw new KoralException(StatusCodes.UNKNOWN_QUERY_ELEMENT,
                     "SRU diagnostic 48: Layer " + identifier
                             + " is unsupported.");
-            koralTerm.setInvalid(true);
         }
 
         koralTerm.setLayer(layer);
     }
 
-    private void parseQualifier(KoralTerm koralTerm, String qualifier) {
+    private void parseQualifier(KoralTerm koralTerm, String qualifier) throws KoralException {
         String layer = koralTerm.getLayer();
         if (layer == null) {
-            koralTerm.setInvalid(true);
             return;
         }
         // Set default foundry
@@ -157,43 +148,36 @@
             }
         }
         else if (qualifier.equals(FOUNDRY_OPENNLP) && layer.equals("l")) {
-            processor
-                    .addError(StatusCodes.UNKNOWN_QUERY_ELEMENT,
+            throw new KoralException(StatusCodes.UNKNOWN_QUERY_ELEMENT,
                             "SRU diagnostic 48: Layer lemma with qualifier opennlp is unsupported.");
-            koralTerm.setInvalid(true);
         }
         else if (!supportedFoundries.contains(qualifier)) {
-            processor.addError(StatusCodes.UNKNOWN_QUERY_ELEMENT,
+            throw new KoralException(StatusCodes.UNKNOWN_QUERY_ELEMENT,
                     "SRU diagnostic 48: Qualifier " + qualifier
                             + " is unsupported.");
-            koralTerm.setInvalid(true);
         }
 
         koralTerm.setFoundry(qualifier);
     }
 
     private void parseOperator(KoralTerm koralTerm, Operator operator,
-            boolean isNot) {
-        MatchOperator matchOperator = null;
+            boolean isNot) throws KoralException {
+    	KoralMatchOperator matchOperator = null;
         if (operator == null || operator == Operator.EQUALS) {
-            matchOperator = isNot ? MatchOperator.NOT_EQUALS
-                    : MatchOperator.EQUALS;
+            matchOperator = isNot ? KoralMatchOperator.NOT_EQUALS : KoralMatchOperator.EQUALS;
         }
         else if (operator == Operator.NOT_EQUALS) {
-            matchOperator = isNot ? MatchOperator.EQUALS
-                    : MatchOperator.NOT_EQUALS;
+            matchOperator = isNot ? KoralMatchOperator.EQUALS : KoralMatchOperator.NOT_EQUALS;
         }
         else {
-            processor
-                    .addError(StatusCodes.UNKNOWN_QUERY_ELEMENT,
+        	throw new KoralException(StatusCodes.UNKNOWN_QUERY_ELEMENT,
                             "SRU diagnostic 37:" + operator.name()
                                     + " is unsupported.");
-            koralTerm.setInvalid(true);
         }
-        koralTerm.setOperator(matchOperator.toString());
+        koralTerm.setOperator(matchOperator);
     }
 
-    private void parseRegexFlags(KoralTerm koralTerm, Set<RegexFlag> set) {
+    private void parseRegexFlags(KoralTerm koralTerm, Set<RegexFlag> set) throws KoralException {
         // default case sensitive
         if (set != null) {
             for (RegexFlag f : set) {
@@ -204,10 +188,9 @@
                     koralTerm.setCaseSensitive(false);
                 }
                 else {
-                    processor.addError(StatusCodes.UNKNOWN_QUERY_ELEMENT,
+                	throw new KoralException(StatusCodes.UNKNOWN_QUERY_ELEMENT,
                             "SRU diagnostic 48:" + f.name()
                                     + " is unsupported.");
-                    koralTerm.setInvalid(true);
                 }
             }
         }
diff --git a/src/main/java/de/ids_mannheim/korap/query/parse/fcsql/FCSSRUQueryParser.java b/src/main/java/de/ids_mannheim/korap/query/parse/fcsql/FCSSRUQueryParser.java
index a1c981f..2c83c5d 100644
--- a/src/main/java/de/ids_mannheim/korap/query/parse/fcsql/FCSSRUQueryParser.java
+++ b/src/main/java/de/ids_mannheim/korap/query/parse/fcsql/FCSSRUQueryParser.java
@@ -4,14 +4,15 @@
 import java.util.Arrays;
 import java.util.List;
 
-import de.ids_mannheim.korap.query.elements.KoralGroup;
-import de.ids_mannheim.korap.query.elements.KoralOperation;
-import de.ids_mannheim.korap.query.elements.KoralGroup.Frame;
-import de.ids_mannheim.korap.query.elements.KoralSpan;
-import de.ids_mannheim.korap.query.elements.MatchOperator;
-import de.ids_mannheim.korap.query.elements.Scope;
-import de.ids_mannheim.korap.query.serialize.FCSQLQueryProcessor;
+import de.ids_mannheim.korap.query.object.KoralContext;
+import de.ids_mannheim.korap.query.serialize.util.KoralException;
 import de.ids_mannheim.korap.query.serialize.util.StatusCodes;
+import de.ids_mannheim.korap.query.object.KoralGroup;
+import de.ids_mannheim.korap.query.object.KoralObject;
+import de.ids_mannheim.korap.query.object.KoralOperation;
+import de.ids_mannheim.korap.query.object.KoralSpan;
+import de.ids_mannheim.korap.query.object.KoralTerm;
+import de.ids_mannheim.korap.query.object.KoralGroup.Frame;
 import eu.clarin.sru.server.fcs.parser.QueryDisjunction;
 import eu.clarin.sru.server.fcs.parser.QueryGroup;
 import eu.clarin.sru.server.fcs.parser.QueryNode;
@@ -19,6 +20,7 @@
 import eu.clarin.sru.server.fcs.parser.QuerySequence;
 import eu.clarin.sru.server.fcs.parser.QueryWithWithin;
 import eu.clarin.sru.server.fcs.parser.SimpleWithin;
+import eu.clarin.sru.server.fcs.parser.SimpleWithin.Scope;
 
 /**
  * @author margaretha
@@ -26,15 +28,13 @@
  */
 public class FCSSRUQueryParser {
 
-    private FCSQLQueryProcessor processor;
     private ExpressionParser expressionParser;
 
-    public FCSSRUQueryParser (FCSQLQueryProcessor processor) {
-        this.processor = processor;
-        this.expressionParser = new ExpressionParser(processor);
+    public FCSSRUQueryParser () {
+        this.expressionParser = new ExpressionParser();
     }
 
-    public Object parseQueryNode(QueryNode queryNode) {
+    public KoralObject parseQueryNode(QueryNode queryNode) throws KoralException {
 
         if (queryNode instanceof QuerySegment) {
             return parseQuerySegment((QuerySegment) queryNode);
@@ -49,57 +49,58 @@
         else if (queryNode instanceof QueryDisjunction) {
             return parseGroupQuery(queryNode.getChildren(),
                     KoralOperation.DISJUNCTION);
-        }
-        else if (queryNode instanceof QueryWithWithin) {
-            return parseWithinQuery((QueryWithWithin) queryNode);
-        }
-        else if (queryNode instanceof SimpleWithin) {
-            return parseFrame((SimpleWithin) queryNode);
-        }
+        } else if (queryNode instanceof QueryWithWithin) {
+        	return parseWithinQuery((QueryWithWithin)queryNode);
+	    } else if (queryNode instanceof SimpleWithin) {
+	    	SimpleWithin withinNode = (SimpleWithin) queryNode;
+	    	return parseWithinScope(withinNode.getScope());
+	    }
         else {
-            processor.addError(StatusCodes.QUERY_TOO_COMPLEX,
+            throw new KoralException(StatusCodes.QUERY_TOO_COMPLEX,
                     "FCS diagnostic 11:" + queryNode.getNodeType().name()
                             + " is currently unsupported.");
-            return null;
         }
     }
+    private KoralObject parseWithinQuery(QueryWithWithin queryNode) throws KoralException {
+    	KoralGroup koralGroup = new KoralGroup(KoralOperation.POSITION);
+    	koralGroup.setFrames(Arrays.asList(Frame.IS_AROUND));
+    	
+    	List<KoralObject> operands = new ArrayList<KoralObject>();
+    	operands.add(parseQueryNode(queryNode.getWithin()));
+    	operands.add(parseQueryNode(queryNode.getQuery()));
+    	koralGroup.setOperands(operands);
+    	return koralGroup;
+	}
 
-    private KoralSpan parseFrame(SimpleWithin frame) {
-        String foundry = "base";
-        String layer = "s"; // structure
+    private KoralSpan parseWithinScope(Scope scope) throws KoralException{
+    	if (scope == null){
+    		throw new KoralException(StatusCodes.MALFORMED_QUERY,
+                    "FCS diagnostic 11: Within context is missing.");
+    	}
 
-        if (frame.getScope() == null) {
-            processor.addError(StatusCodes.MALFORMED_QUERY,
-                    "FCS diagnostic 10: Within context is missing.");
-        }
-        switch (frame.getScope()) {
-            case SENTENCE:
-                return new KoralSpan(Scope.SENTENCE.toString(), foundry, layer,
-                        MatchOperator.EQUALS);
-            default:
-                processor.addError(StatusCodes.QUERY_TOO_COMPLEX,
-                        "FCS diagnostic 11:" + frame.toString()
-                                + " is currently unsupported.");
-                return null;
-        }
+    	KoralContext contextSpan;
+    	if (scope == Scope.SENTENCE) {
+			contextSpan = KoralContext.SENTENCE;
+    	}
+    	else if (scope == Scope.PARAGRAPH){
+			contextSpan = KoralContext.PARAGRAPH;
+    	}
+    	else if (scope == Scope.TEXT){
+            contextSpan = KoralContext.TEXT;
+    	}
+    	else{
+    		throw new KoralException(StatusCodes.QUERY_TOO_COMPLEX,
+                    "FCS diagnostic 11: Within scope " + scope.toString()
+                            + " is currently unsupported.");
+    	}
+    	
+    	return new KoralSpan(new KoralTerm(contextSpan));
     }
-
-    private KoralGroup parseWithinQuery(QueryWithWithin queryNode) {
-        KoralGroup koralGroup = new KoralGroup(KoralOperation.POSITION);
-        koralGroup.setFrames(Arrays.asList(Frame.IS_AROUND));
-
-        List<Object> operands = new ArrayList<Object>();
-        operands.add(parseQueryNode(queryNode.getWithin()));
-        operands.add(parseQueryNode(queryNode.getChild(0)));
-        koralGroup.setOperands(operands);
-
-        return koralGroup;
-    }
-
-    private KoralGroup parseGroupQuery(List<QueryNode> children,
-            KoralOperation operation) {
+    
+	private KoralGroup parseGroupQuery(List<QueryNode> children,
+            KoralOperation operation) throws KoralException {
         KoralGroup koralGroup = new KoralGroup(operation);
-        List<Object> operands = new ArrayList<Object>();
+        List<KoralObject> operands = new ArrayList<KoralObject>();
         for (QueryNode child : children) {
             operands.add(parseQueryNode(child));
         }
@@ -107,14 +108,13 @@
         return koralGroup;
     }
 
-    private Object parseQuerySegment(QuerySegment segment) {
+    private KoralObject parseQuerySegment(QuerySegment segment) throws KoralException {
         if ((segment.getMinOccurs() == 1) && (segment.getMaxOccurs() == 1)) {
             return expressionParser.parseExpression(segment.getExpression());
         }
         else {
-            processor.addError(StatusCodes.QUERY_TOO_COMPLEX,
+            throw new KoralException(StatusCodes.QUERY_TOO_COMPLEX,
                     "FCS diagnostic 11: Query is too complex.");
-            return null;
         }
     }
 }
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/FCSQLQueryProcessor.java b/src/main/java/de/ids_mannheim/korap/query/serialize/FCSQLQueryProcessor.java
index d2b9d7a..369e8e3 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/FCSQLQueryProcessor.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/FCSQLQueryProcessor.java
@@ -3,6 +3,7 @@
 import java.util.Map;
 
 import de.ids_mannheim.korap.query.parse.fcsql.FCSSRUQueryParser;
+import de.ids_mannheim.korap.query.serialize.util.KoralException;
 import de.ids_mannheim.korap.query.serialize.util.StatusCodes;
 import eu.clarin.sru.server.SRUQueryBase;
 import eu.clarin.sru.server.fcs.Constants;
@@ -50,7 +51,11 @@
             FCSSRUQuery fcsSruQuery = parseQueryStringtoFCSQuery(query);
             if (fcsSruQuery != null) {
                 QueryNode fcsQueryNode = fcsSruQuery.getParsedQuery();
-                parseFCSQueryToKoralQuery(fcsQueryNode);
+                try {
+					parseFCSQueryToKoralQuery(fcsQueryNode);
+				} catch (KoralException e) {
+					addError(e.getStatusCode(), e.getMessage());
+				}
             }
         }
     }
@@ -95,8 +100,8 @@
         return fcsQuery;
     }
 
-    private void parseFCSQueryToKoralQuery(QueryNode queryNode) {
-        FCSSRUQueryParser parser = new FCSSRUQueryParser(this);
+    private void parseFCSQueryToKoralQuery(QueryNode queryNode) throws KoralException {
+        FCSSRUQueryParser parser = new FCSSRUQueryParser();
         Object o = parser.parseQueryNode(queryNode);
         Map<String, Object> queryMap = MapBuilder.buildQueryMap(o);
         if (queryMap != null) requestMap.put("query", queryMap);
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/MapBuilder.java b/src/main/java/de/ids_mannheim/korap/query/serialize/MapBuilder.java
index 531b389..9d1c2ee 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/MapBuilder.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/MapBuilder.java
@@ -2,11 +2,11 @@
 
 import java.util.Map;
 
-import de.ids_mannheim.korap.query.elements.KoralGroup;
-import de.ids_mannheim.korap.query.elements.KoralSpan;
-import de.ids_mannheim.korap.query.elements.KoralTerm;
-import de.ids_mannheim.korap.query.elements.KoralTermGroup;
-import de.ids_mannheim.korap.query.elements.KoralToken;
+import de.ids_mannheim.korap.query.object.KoralGroup;
+import de.ids_mannheim.korap.query.object.KoralSpan;
+import de.ids_mannheim.korap.query.object.KoralTerm;
+import de.ids_mannheim.korap.query.object.KoralTermGroup;
+import de.ids_mannheim.korap.query.object.KoralToken;
 
 /**
  * @author margaretha
@@ -32,9 +32,9 @@
                 KoralTermGroup termGroup = (KoralTermGroup) o;
                 return termGroup.buildMap();
             }
-            else if (o instanceof KoralSpan) {
-                KoralSpan span = (KoralSpan) o;
-                return span.buildMap();
+            else if (o instanceof KoralSpan){
+            	KoralSpan span = (KoralSpan) o;
+            	return span.buildMap();
             }
         }
         return null;
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/util/KoralException.java b/src/main/java/de/ids_mannheim/korap/query/serialize/util/KoralException.java
new file mode 100644
index 0000000..34d4569
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/util/KoralException.java
@@ -0,0 +1,30 @@
+package de.ids_mannheim.korap.query.serialize.util;
+
+public class KoralException extends Exception{
+
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 5463242042200109417L;
+	private int statusCode;
+	
+	public KoralException(int code, String message) {
+		super(message);
+		this.statusCode = code;
+	}
+	
+	public KoralException(int code, String message, Throwable cause) {
+        super(message, cause);
+        this.statusCode = code;
+    }
+
+	public int getStatusCode() {
+		return statusCode;
+	}
+
+	public void setStatusCode(int statusCode) {
+		this.statusCode = statusCode;
+	}
+
+	
+}
diff --git a/src/test/java/de/ids_mannheim/korap/query/serialize/FCSQLQueryProcessorTest.java b/src/test/java/de/ids_mannheim/korap/query/serialize/FCSQLQueryProcessorTest.java
index 2afb7cb..475606a 100644
--- a/src/test/java/de/ids_mannheim/korap/query/serialize/FCSQLQueryProcessorTest.java
+++ b/src/test/java/de/ids_mannheim/korap/query/serialize/FCSQLQueryProcessorTest.java
@@ -291,18 +291,16 @@
                 + "]}";
         runAndValidate(query, jsonLd);
     }
-
+    
     @Test
     public void testWithinQuery() throws JsonProcessingException {
-        String query = "[pos=\"VVFIN\"] within s";
-        String jsonLd = "{@type:koral:group,"
-                + "operation:operation:position,"
-                + "frames:["
-                + "frames:isAround"
-                + "],"
-                + "operands:[{@type: koral:span,key:s,foundry:base,layer:s,match:match:eq},"
-                + "{@type:koral:token,wrap:{@type:koral:term,key:VVFIN,foundry:tt,layer:p,type:type:regex,match:match:eq}}"
-                + "]}";
-        runAndValidate(query, jsonLd);
-    }
+    	String query = "[cnx:pos=\"VVFIN\"] within s";
+    	String jsonLd = "{@type:koral:group,"
+    			+ "operation:operation:position,"
+    			+ "operands:["
+    			+ "{@type:koral:span,wrap:{@type:koral:term,key:s,foundry:base,layer:s}},"
+    			+ "{@type:koral:token,wrap:{@type:koral:term,key:VVFIN,foundry:cnx,layer:p,type:type:regex,match:match:eq}}"
+    			+ "]}";
+    	runAndValidate(query, jsonLd);
+	}
 }