changed foundry/layer specification for (pointing) relations. introduced "korap:edge" to represent edges and their properties
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/AbstractSyntaxTree.java b/src/main/java/de/ids_mannheim/korap/query/serialize/AbstractSyntaxTree.java
index 562ce66..c7b1655 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/AbstractSyntaxTree.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/AbstractSyntaxTree.java
@@ -18,6 +18,8 @@
 	public abstract Map<String, Object> getRequestMap();
 
 	public abstract void process(String query) throws QueryException;
+	
+	public static final Integer MAXIMUM_DISTANCE = 100; 
 
 	protected LinkedHashMap<String, Object> makeSpan() {
 		LinkedHashMap<String, Object> span = new LinkedHashMap<String, Object>();
@@ -30,7 +32,7 @@
 		term.put("@type", "korap:term");
 		return term;
 	}
-
+	
 	protected LinkedHashMap<String, Object> makeToken() {
 		LinkedHashMap<String, Object> token = new LinkedHashMap<String, Object>();
 		token.put("@type", "korap:token");
@@ -45,6 +47,28 @@
 		return group;
 	}
 	
+	protected LinkedHashMap<String, Object> makeTreeRelation(String reltype) {
+		LinkedHashMap<String, Object> group = new LinkedHashMap<String, Object>();
+		group.put("@type", "korap:treeRelation");
+		if (reltype != null) group.put("reltype", reltype);
+		return group;
+	}
+	
+	protected LinkedHashMap<String, Object> makeRelation(String reltype) {
+		LinkedHashMap<String, Object> group = new LinkedHashMap<String, Object>();
+		group.put("@type", "korap:relation");
+		if (reltype != null) group.put("reltype", reltype);
+		return group;
+	}
+	
+	protected LinkedHashMap<String, Object> makeBoundary(int min, int max) {
+		LinkedHashMap<String, Object> group = new LinkedHashMap<String, Object>();
+		group.put("@type", "korap:boundary");
+		group.put("min", min);
+		group.put("max", max);
+		return group;
+	}
+	
 	protected void addOperandsToGroup(LinkedHashMap<String, Object> group) {
 		ArrayList<Object> operands = new ArrayList<Object>();
 		group.put("operands", operands);
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/AqlTree.java b/src/main/java/de/ids_mannheim/korap/query/serialize/AqlTree.java
index 6589659..493cb47 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/AqlTree.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/AqlTree.java
@@ -228,8 +228,8 @@
 			// get referenced operands
 			// TODO generalize operator
 			// TODO capture variableExprs
-			LinkedHashMap<String, Object> group = makeGroup("treeRelation");
-			group.put("treeRelation", parseOperatorNode(node.getChild(1).getChild(0)));
+			LinkedHashMap<String, Object> group = makeGroup("relation");
+			group.put("relation", parseOperatorNode(node.getChild(1).getChild(0)));
 			List<Object> operands = (List<Object>) group.get("operands");
 			for (ParseTree refOrNode : getChildrenWithCat(node, "refOrNode")) {
 				String ref = refOrNode.getChild(0).toStringTree(parser).substring(1);
@@ -313,43 +313,92 @@
 	}
 
 
-
-
-
 	private LinkedHashMap<String, Object> parseOperatorNode(ParseTree operatorNode) {
-		LinkedHashMap<String, Object> treeRelation = new LinkedHashMap<String, Object>();
-		treeRelation.put("@type", "korap:treeRelation");
+		LinkedHashMap<String, Object> relation = null;
 		String operator = getNodeCat(operatorNode);
-		// TODO complete (check Antlr grammar)
+		// DOMINANCE
 		if (operator.equals("dominance")) {
-			treeRelation.put("reltype", "dominance");
+			relation = makeTreeRelation("dominance");
 			ParseTree leftChildSpec = getFirstChildWithCat(operatorNode, "@l");
 			ParseTree rightChildSpec = getFirstChildWithCat(operatorNode, "@r");
+			ParseTree qName = getFirstChildWithCat(operatorNode, "qName");
 			ParseTree edgeSpec = getFirstChildWithCat(operatorNode, "edgeSpec");
-			System.err.println(edgeSpec);
-			if (leftChildSpec != null) treeRelation.put("index", 0);
-			if (rightChildSpec != null) treeRelation.put("index", -1);
-			if (edgeSpec != null) {
-				for (ParseTree edgeAnno : getChildrenWithCat(edgeSpec, "edgeAnno")) {
-					treeRelation.putAll(parseEdgeAnno(edgeAnno));
-				}
-			}
+			ParseTree star = getFirstChildWithCat(operatorNode, "*");
+			ParseTree rangeSpec = getFirstChildWithCat(operatorNode, "rangeSpec");
+			if (leftChildSpec != null) relation.put("index", 0);
+			if (rightChildSpec != null) relation.put("index", -1);
+			if (qName != null) relation.putAll(parseQNameNode(qName));
+			if (edgeSpec != null) relation.put("edges", parseEdgeSpec(edgeSpec)) ;
+			if (star != null) relation.put("boundary", makeBoundary(0, 100));
+			if (rangeSpec != null) relation.put("boundary", parseRangeSpec(rangeSpec));
+			
 		}
-		return treeRelation;
+		else if (operator.equals("pointing")) {
+//			String reltype = operatorNode.getChild(1).toStringTree(parser);
+			relation = makeRelation(null);
+			ParseTree qName = getFirstChildWithCat(operatorNode, "qName");
+			ParseTree edgeSpec = getFirstChildWithCat(operatorNode, "edgeSpec");
+			ParseTree star = getFirstChildWithCat(operatorNode, "*");
+			ParseTree rangeSpec = getFirstChildWithCat(operatorNode, "rangeSpec");
+			if (qName != null) relation.putAll(parseQNameNode(qName));
+			if (edgeSpec != null) relation.put("edges", parseEdgeSpec(edgeSpec)) ;
+			if (star != null) relation.put("boundary", makeBoundary(0, 100));
+			if (rangeSpec != null) relation.put("boundary", parseRangeSpec(rangeSpec));
+			
+		}
+		else if (operator.equals("precedence")) {
+			
+		}
+		else if (operator.equals("spanrelation")) {
+			
+		}
+		else if (operator.equals("commonparent")) {
+			
+		}
+		else if (operator.equals("commonancestor")) {
+			
+		}
+		else if (operator.equals("identity")) {
+			
+		}
+		else if (operator.equals("equalvalue")) {
+			
+		}
+		else if (operator.equals("notequalvalue")) {
+			
+		}
+		return relation;
+	}
+
+	private Object parseEdgeSpec(ParseTree edgeSpec) {
+		ArrayList<Object> edgeAnnos = new ArrayList<Object>();
+		for (ParseTree edgeAnno : getChildrenWithCat(edgeSpec, "edgeAnno")) {
+			edgeAnnos.add(parseEdgeAnno(edgeAnno));
+		}
+		return edgeAnnos;
 	}
 
 	private LinkedHashMap<String, Object> parseEdgeAnno(
 			ParseTree edgeAnnoSpec) {
 		LinkedHashMap<String, Object> edgeAnno = new LinkedHashMap<String, Object>();
-		ParseTree qNameNode = edgeAnnoSpec.getChild(0);
+		edgeAnno.put("@type", "korap:edge");
+		ParseTree labelNode = edgeAnnoSpec.getChild(0);
 		ParseTree matchOperatorNode = edgeAnnoSpec.getChild(1);
 		ParseTree textSpecNode = edgeAnnoSpec.getChild(2);
-		edgeAnno.putAll(parseQNameNode(qNameNode));
+		edgeAnno.put("label", labelNode.getChild(0).toStringTree(parser));
 		edgeAnno.putAll(parseTextSpec(textSpecNode));
 		edgeAnno.put("match", parseMatchOperator(matchOperatorNode));
 		return edgeAnno;
 	}
 
+	private LinkedHashMap<String, Object> parseRangeSpec(ParseTree rangeSpec) {
+		Integer min = Integer.parseInt(rangeSpec.getChild(0).toStringTree(parser));
+		Integer max = MAXIMUM_DISTANCE;
+		if (rangeSpec.getChildCount()==3) 
+			max = Integer.parseInt(rangeSpec.getChild(2).toStringTree(parser));
+		return makeBoundary(min, max);
+	}
+	
 	private LinkedHashMap<String, Object> parseTextSpec(ParseTree node) {
 		LinkedHashMap<String, Object> term = new LinkedHashMap<String, Object>();
 		if (hasChild(node, "regex")) {
@@ -393,14 +442,11 @@
 
 
 	private LinkedHashMap<String, Object> parseQNameNode(ParseTree node) {
-		System.err.println(getNodeCat(node));
 		LinkedHashMap<String, Object> fields = new LinkedHashMap<String, Object>();
-		if (node.getChildCount() == 1) { 									// only layer specification
-			fields.put("layer", node.getChild(0).toStringTree(parser));
-		} else if (node.getChildCount() == 3) {								// foundry / layer specification
-			fields.put("foundry", node.getChild(0).toStringTree(parser));
-			fields.put("layer", node.getChild(2).toStringTree(parser));
-		}
+		ParseTree layerNode = getFirstChildWithCat(node, "layer");
+		ParseTree foundryNode = getFirstChildWithCat(node, "foundry");
+		if (foundryNode != null) fields.put("foundry", foundryNode.getChild(0).toStringTree(parser));
+		fields.put("layer", layerNode.getChild(0).toStringTree(parser));
 		return fields;
 	}
 
@@ -491,9 +537,11 @@
 			"tok!=/Frau/",
 			"node",
 			"treetagger/pos=\"NN\"",
-			
-			"node & node & #2 >@r[foundry/layer=\"key\"] #1",
-			"node & node & #2 > #1",
+			"node & node & #2 ->foundry/dep[anno=\"key\"],2,4 #1",
+			"tiger/pos=\"NN\" >cnx/cat  node",
+			 "\"Mann\" & node & #2 >[cat=\"NP\"] #1"
+
+//			"node & node & #2 ->[foundry/layer=\"key\"],2,4 #1",
 			};
 //		AqlTree.verbose=true;
 		for (String q : queries) {
diff --git a/src/test/java/AqlTreeTest.java b/src/test/java/AqlTreeTest.java
index f5ae532..ccb9eaf 100644
--- a/src/test/java/AqlTreeTest.java
+++ b/src/test/java/AqlTreeTest.java
@@ -82,10 +82,10 @@
 	public void testSimpleDominance() throws QueryException {
 		query = "node & node & #2 > #1";
 		String dom1 = 
-				"{@type=korap:group, operation=operation:treeRelation, operands=[" +
+				"{@type=korap:group, operation=operation:relation, operands=[" +
 						"{@type=korap:span}," +
 						"{@type=korap:span}" +
-				"], treeRelation={@type=korap:treeRelation, reltype=dominance}" +
+				"], relation={@type=korap:treeRelation, reltype=dominance}" +
 				"}";
 		aqlt = new AqlTree(query);
 		map = aqlt.getRequestMap().get("query").toString();
@@ -93,36 +93,48 @@
 		
 		query = "\"Mann\" & node & #2 > #1";
 		String dom2 = 
-				"{@type=korap:group, operation=operation:treeRelation, operands=[" +
+				"{@type=korap:group, operation=operation:relation, operands=[" +
 						"{@type=korap:span}," +
 						"{@type=korap:token, wrap={@type=korap:term, key=Mann, match=match:eq}}" +
-				"], treeRelation={@type=korap:treeRelation, reltype=dominance}" +
+				"], relation={@type=korap:treeRelation, reltype=dominance}" +
 				"}";
 		aqlt = new AqlTree(query);
 		map = aqlt.getRequestMap().get("query").toString();
 		assertEquals(dom2.replaceAll(" ", ""), map.replaceAll(" ", ""));
 		
-		query = "\"Mann\" & node & #2 >[cnx/cat=\"NP\"] #1";
+		query = "\"Mann\" & node & #2 >[cat=\"NP\"] #1";
 		String dom3 = 
-				"{@type=korap:group, operation=operation:treeRelation, operands=[" +
+				"{@type=korap:group, operation=operation:relation, operands=[" +
 						"{@type=korap:span}," +
 						"{@type=korap:token, wrap={@type=korap:term, key=Mann, match=match:eq}}" +
-				"], treeRelation={@type=korap:treeRelation, reltype=dominance, foundry=cnx, layer=cat, key=NP, match=match:eq}" +
+				"], relation={@type=korap:treeRelation, reltype=dominance, edges=[{@type=korap:edge, label=cat, key=NP, match=match:eq}]}" +
 				"}";
 		aqlt = new AqlTree(query);
 		map = aqlt.getRequestMap().get("query").toString();
 		assertEquals(dom3.replaceAll(" ", ""), map.replaceAll(" ", ""));
 		
-		query = "\"Mann\" & node & #2 >@l[cnx/cat=\"NP\"] #1";
+		query = "\"Mann\" & node & #2 >@l[cat=\"NP\"] #1";
 		String dom4 = 
-				"{@type=korap:group, operation=operation:treeRelation, operands=[" +
+				"{@type=korap:group, operation=operation:relation, operands=[" +
 						"{@type=korap:span}," +
 						"{@type=korap:token, wrap={@type=korap:term, key=Mann, match=match:eq}}" +
-				"], treeRelation={@type=korap:treeRelation, reltype=dominance, index=0, foundry=cnx, layer=cat, key=NP, match=match:eq}" +
+				"], relation={@type=korap:treeRelation, reltype=dominance, index=0, edges=[{@type=korap:edge, label=cat, key=NP, match=match:eq}]}" +
 				"}";
 		aqlt = new AqlTree(query);
 		map = aqlt.getRequestMap().get("query").toString();
 		assertEquals(dom4.replaceAll(" ", ""), map.replaceAll(" ", ""));
+		
+		query = "\"Mann\" & node & #2 >2,4 #1";
+		String dom5 = 
+				"{@type=korap:group, operation=operation:relation, operands=[" +
+						"{@type=korap:span}," +
+						"{@type=korap:token, wrap={@type=korap:term, key=Mann, match=match:eq}}" +
+				"], relation={@type=korap:treeRelation, reltype=dominance, " +
+						"boundary={@type=korap:boundary, min=2, max=4}}" +
+				"}";
+		aqlt = new AqlTree(query);
+		map = aqlt.getRequestMap().get("query").toString();
+		assertEquals(dom5.replaceAll(" ", ""), map.replaceAll(" ", ""));
 	}