PQ empty tokens as distance groups, Cosmas elem -> element
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/CosmasTree.java b/src/main/java/de/ids_mannheim/korap/query/serialize/CosmasTree.java
index 7f5d257..beb2c38 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/CosmasTree.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/CosmasTree.java
@@ -218,7 +218,7 @@
 		}
 		
 		// Nodes introducing tokens. Process all in the same manner, except for the fieldMap entry
-		if (nodeCat.equals("OPWF") || nodeCat.equals("OPLEM") || nodeCat.equals("OPMORPH")) {
+		if (nodeCat.equals("OPWF") || nodeCat.equals("OPLEM")) {
 			
 			//Step I: get info
 			LinkedHashMap<String, Object> token = new LinkedHashMap<String, Object>();
@@ -230,18 +230,10 @@
 			
 			fieldMap.put("@type", "korap:term");			
 			// make category-specific fieldMap entry
-			String value = "";
-			if (nodeCat.equals("OPWF")) {
-				value = "orth:"+node.getChild(0).toStringTree().replaceAll("\"", "");
-			}
-			if (nodeCat.equals("OPLEM")) {
-				value = "base:"+node.getChild(0).toStringTree().replaceAll("\"", "");
-			}
-			if (nodeCat.equals("OPMORPH")) {
-				value = "morph:"+node.toStringTree();
-				//TODO decompose morphology query
-			}
+			String attr = nodeCat.equals("OPWF") ? "orth:" : "base:";
+			String value = attr+node.getChild(0).toStringTree().replaceAll("\"", "");
 			fieldMap.put("@value", value);
+			
 			// negate field (see above)
 			if (negate) {
 				fieldMap.put("relation", "!=");
@@ -252,10 +244,57 @@
 			putIntoSuperObject(token, 1);
 		}
 		
+		if (nodeCat.equals("OPMORPH")) {
+			//Step I: get info
+			LinkedHashMap<String, Object> token = new LinkedHashMap<String, Object>();
+			token.put("@type", "korap:token");
+			
+			List<String> morphValues = QueryUtils.parseMorph(node.getChild(0).toStringTree());
+			if (morphValues.size() == 1) {
+				LinkedHashMap<String, Object> fieldMap = new LinkedHashMap<String, Object>();
+				token.put("@value", fieldMap);
+				
+				fieldMap.put("@type", "korap:term");
+				fieldMap.put("@value", morphValues.get(0));
+				// make category-specific fieldMap entry
+				// negate field (see above)
+				if (negate) {
+					fieldMap.put("relation", "!=");
+				} else {
+					fieldMap.put("relation", "=");
+				}
+			} else {
+				LinkedHashMap<String, Object> conjGroup = new LinkedHashMap<String, Object>();
+				token.put("@value", conjGroup);
+				ArrayList<Object> conjOperands = new ArrayList<Object>();
+				conjGroup.put("@type", "korap:group");
+				conjGroup.put("relation", "and");
+				conjGroup.put("operands", conjOperands);
+				for (String value : morphValues) {
+					LinkedHashMap<String, Object> fieldMap = new LinkedHashMap<String, Object>();
+					token.put("@value", fieldMap);
+					
+					fieldMap.put("@type", "korap:term");
+					fieldMap.put("@value", value);
+					// make category-specific fieldMap entry
+					// negate field (see above)
+					if (negate) {
+						fieldMap.put("relation", "!=");
+					} else {
+						fieldMap.put("relation", "=");
+					}
+				}
+			}
+			
+			
+			//Step II: decide where to put
+			putIntoSuperObject(token, 0);
+		}
+		
 		if (nodeCat.equals("OPELEM")) {
 			// Step I: create element
 			LinkedHashMap<String, Object> elem = new LinkedHashMap<String, Object>();
-			elem.put("@type", "korap:elem");
+			elem.put("@type", "korap:element");
 			elem.put("@value", node.getChild(0).getChild(0).toStringTree().toLowerCase());
 			//Step II: decide where to put
 			putIntoSuperObject(elem);
@@ -264,7 +303,7 @@
 		if (nodeCat.equals("OPLABEL")) {
 			// Step I: create element
 			LinkedHashMap<String, Object> elem = new LinkedHashMap<String, Object>();
-			elem.put("@type", "korap:elem");
+			elem.put("@type", "korap:element");
 			elem.put("@value", node.getChild(0).toStringTree().replaceAll("<|>", ""));
 			//Step II: decide where to put
 			putIntoSuperObject(elem);
@@ -440,7 +479,7 @@
 				posgroup.put("operands", operands);
 				LinkedHashMap<String, Object> bedElem = new LinkedHashMap<String, Object>();
 				operands.add(bedElem);
-				bedElem.put("@type", "korap:elem");
+				bedElem.put("@type", "korap:element");
 				bedElem.put("@value", c.elem);
 				objectStack.push(posgroup);
 				stackedObjects++;
@@ -474,7 +513,7 @@
 					posGroup.put("operands", posOperands);
 					LinkedHashMap<String, Object> bedElem = new LinkedHashMap<String, Object>();
 					posOperands.add(bedElem);
-					bedElem.put("@type", "korap:elem");
+					bedElem.put("@type", "korap:element");
 					bedElem.put("@value", c.elem);
 					
 					
@@ -528,6 +567,8 @@
 	}
 
 	
+	
+
 	private void parseOPINOptions(Tree node, LinkedHashMap<String, Object> posgroup) {
 		Tree posnode = QueryUtils.getFirstChildWithCat(node, "POS");
 		Tree rangenode = QueryUtils.getFirstChildWithCat(node, "RANGE");
@@ -683,6 +724,7 @@
 		 */
 		String[] queries = new String[] {
 				/* COSMAS 2 */
+				"MORPH(V)"
 				};
 		CosmasTree.debug=true;
 		for (String q : queries) {
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusTree.java b/src/main/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusTree.java
index bd58449..b10105c 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusTree.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusTree.java
@@ -277,13 +277,44 @@
 				}
 				// Step I: decide type of element (one or more elements? -> token or sequence)
 				// take into account a possible 'occ' child with accompanying parantheses, therefore 3 extra children
+				// TODO analyse emptysegments
 				int occExtraChildren = cqHasOccChild ? 3:0;
 				if (node.getChildCount()>1 + occExtraChildren) {
-					sequence.put("@type", "korap:sequence");
-					ArrayList<Object> sequenceOperands = new ArrayList<Object>();
-					sequence.put("operands", sequenceOperands);
-					objectStack.push(sequence);
-					stackedObjects++;
+					ParseTree emptySegments = QueryUtils.getFirstChildWithCat(node, "empty_segments");
+					if (emptySegments != null && emptySegments != node.getChild(0)) {
+						String[] minmax = parseEmptySegments(emptySegments);
+						Integer min = Integer.parseInt(minmax[0]);
+						Integer max = Integer.parseInt(minmax[1]);
+						sequence.put("@type", "korap:group");
+						sequence.put("relation", "distance");
+						sequence.put("@subtype", "incl");
+						ArrayList<Object> constraint = new ArrayList<Object>(); 
+						sequence.put("constraint", constraint);
+						ArrayList<Object> sequenceOperands = new ArrayList<Object>();
+						sequence.put("operands", sequenceOperands);
+						objectStack.push(sequence);
+						stackedObjects++;
+						LinkedHashMap<String, Object> distMap = new LinkedHashMap<String, Object>();
+						constraint.add(distMap);
+						distMap.put("@type", "korap:distance");
+						distMap.put("measure", "w");
+						distMap.put("direction", "plus");
+						distMap.put("min", min);
+						distMap.put("max", max);
+					} else {
+						sequence.put("@type", "korap:sequence");
+						ArrayList<Object> sequenceOperands = new ArrayList<Object>();
+						if (emptySegments != null) {
+							String[] minmax = parseEmptySegments(emptySegments);
+							Integer min = Integer.parseInt(minmax[0]);
+							Integer max = Integer.parseInt(minmax[1]);
+							sequence.put("offset-min", min);
+							sequence.put("offset-max", max);
+						}
+						sequence.put("operands", sequenceOperands);
+						objectStack.push(sequence);
+						stackedObjects++;
+					}
 				} else {
 					// if only child, make the sequence a mere korap:token...
 					// ... but only if it has a real token/element beneath it
@@ -363,15 +394,15 @@
 			// take into account a possible 'occ' child
 			if (node.getParent().getChildCount()>1) {				
 				if (node.getText().equals("[]")) {
-					LinkedHashMap<String, Object> sequence  = objectStack.get(onTopOfObjectStack);
-					String offsetStr = (String) sequence.get("offset");
-					if (offsetStr == null) {
-						sequence.put("offset", "1");
-					} else {
-						Integer offset = Integer.parseInt(offsetStr);
-						sequence.put("offset", offset+1);
-					}
-					
+//					LinkedHashMap<String, Object> sequence  = objectStack.get(onTopOfObjectStack);
+//					String offsetStr = (String) sequence.get("offset");
+//					if (offsetStr == null) {
+//						sequence.put("offset", "1");
+//					} else {
+//						Integer offset = Integer.parseInt(offsetStr);
+//						sequence.put("offset", offset+1);
+//					}
+//					
 				} else {
 					ArrayList<Object> topSequenceOperands = (ArrayList<Object>) objectStack.get(onTopOfObjectStack).get("operands");
 					topSequenceOperands.add(token);
@@ -657,6 +688,7 @@
 			positionGroup.put("@type", "korap:group");
 			positionGroup.put("relation", "position");
 			positionGroup.put("position", relation.toLowerCase());
+//			positionGroup.put("@subtype", "incl");
 			positionGroup.put("operands", posOperands);
 			// Step II: decide where to put the group
 			// add group to sequence only if it is not an only child (in that case, sq_segments has already added the info and is just waiting for the relevant info)
@@ -783,6 +815,47 @@
 		openNodeCats.pop();
 	}
 
+	private String[] parseEmptySegments(ParseTree emptySegments) {
+		String[] minmax = new String[2];
+		Integer min = 0;
+		Integer max = 0;
+		ParseTree child;
+		for (int i=0; i<emptySegments.getChildCount()-1; i++) {
+			child = emptySegments.getChild(i);
+			ParseTree nextSibling = emptySegments.getChild(i+1);
+			String nextSiblingString = nextSibling.toStringTree(); 
+			System.err.println("FOO "+child.toStringTree());
+			System.out.println("FOO "+nextSiblingString);
+			if (child.toStringTree().equals("[]")) {
+				if (nextSiblingString.equals("?")) {
+					max++;
+				} else if (nextSiblingString.startsWith("{")) {
+					String occ = nextSiblingString.substring(1,nextSiblingString.length()-1);
+					System.out.println(occ);
+					if (occ.contains(",")) {
+						String[] minmaxOcc = occ.split(",");
+						min += Integer.parseInt(minmaxOcc[0]);
+						max += Integer.parseInt(minmaxOcc[1]);
+					} else {
+						min += Integer.parseInt(occ);
+						max += Integer.parseInt(occ);
+					}
+				} else {
+					min++;
+					max++;
+				}
+			}
+		}
+		child = emptySegments.getChild(emptySegments.getChildCount()-1);
+		if (child.toStringTree().equals("[]")) {
+			min++;
+			max++;
+		}
+		minmax[0] = min.toString();
+		minmax[1] = max.toString();
+		return minmax;
+	}
+
 	@SuppressWarnings("unchecked")
 	private void createOccGroup(ParseTree node) {
 		LinkedHashMap<String,Object> occGroup = new LinkedHashMap<String,Object>();
@@ -845,27 +918,9 @@
 		 * For testing
 		 */
 		String[] queries = new String[] {
-//				"shrink(startswith(<s>,{<np>}))",
-//				"shrink(1: startswith(<s>,{1:<np>}))",
-//				"contains(<p>, startswith(<s>,<np>))",
-//				"[base=foo]*",
-//				"[base=foo]*[base=bar]",
-//				"[base=bar][base=foo]*",
-//				"([base=bar][base=foo])*",
-//				"([base=bar][base  =  foo])*",
-//				"<s>([base=bar][base=foo])*",
-//				"<s>[orth=Mann]([base=bar][base=foo])*",
-//				"<s><np>([base=bar][base=foo])*",
-//				"shrink(1:contains(<s>,{1:<np>}))",
-//				"contains(<s>,startswith(<np>,[p=Det]))",
-//				"contains(<s>, startswith(<np>,[p=Det]))",base=c]",
-//				
-				"[orth=der]^[orth=Mann]",
-//				"([base=bar][base=foo])*",
-				"([base=a]^[base=b])|[base=c]",
-				"Baum | Stein",
-				"Haus/i",
-				"startswith(<s>,[]+[base=der][base=Mann])",
+				"startswith(<s>,[][base=der][base=Mann])",
+//				"[][base=Mann]",
+				"[base=Hund][][base=Katze][][][base=Maus]",
 		};
 		PoliqarpPlusTree.debug=true;
 		for (String q : queries) {
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 db60b9e..736b875 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
@@ -20,7 +20,7 @@
 public class QueryUtils {
 
 	/**
-	 * Returns the category (or 'label') of the root of a (sub-)ParseTree.
+	 * Returns the category (or 'label') of the root of a ParseTree (ANTLR 4).
 	 * @param node
 	 * @return
 	 */
@@ -35,7 +35,7 @@
 	}
 	
 	/**
-	 * Returns the category (or 'label') of the root of a ParseTree.
+	 * Returns the category (or 'label') of the root of a ParseTree (ANTLR 3).
 	 * @param node
 	 * @return
 	 */
@@ -65,6 +65,19 @@
 		return false;
 	}
 	
+	public static boolean hasDescendant(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)) {
+				return true;
+			}
+		}
+		return false;
+	}
+	
 	public static List<Tree> getChildrenWithCat(Tree node, String nodeCat) {
 		ArrayList<Tree> children = new ArrayList<Tree>();
 		for (int i=0; i<node.getChildCount(); i++) {
@@ -75,6 +88,16 @@
 		return children;
 	}
 	
+	public static List<ParseTree> getChildrenWithCat(ParseTree node, String nodeCat) {
+		ArrayList<ParseTree> children = new ArrayList<ParseTree>();
+		for (int i=0; i<node.getChildCount(); i++) {
+			if (getNodeCat(node.getChild(i)).equals(nodeCat)) {
+				children.add(node.getChild(i));
+			}
+		}
+		return children;
+	}
+	
 	public static Tree getFirstChildWithCat(Tree node, String nodeCat) {
 		for (int i=0; i<node.getChildCount(); i++) {
 			if (getNodeCat(node.getChild(i)).equals(nodeCat)) {
@@ -84,6 +107,15 @@
 		return null;
 	}
 	
+	public static ParseTree getFirstChildWithCat(ParseTree node, String nodeCat) {
+		for (int i=0; i<node.getChildCount(); i++) {
+			if (getNodeCat(node.getChild(i)).equals(nodeCat)) {
+				return node.getChild(i);
+			}
+		}
+		return null;
+	}
+	
 	public static void checkUnbalancedPars(String q) throws QueryException {
 		int openingPars = StringUtils.countMatches(q, "(");
 		int closingPars = StringUtils.countMatches(q, ")");
@@ -98,6 +130,13 @@
 		if (openingBrcs != closingBrcs) throw new QueryException(
 				"Your query string contains an unbalanced number of braces.");
 	}
+	
+	public static List<String> parseMorph(String stringTree) {
+		
+		ArrayList<String> morph = new ArrayList<String>();
+		System.err.println(stringTree);
+		return morph;
+	}
 
 
     public static String buildCypherQuery(String cypher, String ctypel, String ctyper,
@@ -222,6 +261,10 @@
         return request;
     }
 
+	
+
+	
+
 
 
 }
diff --git a/src/test/java/CosmasTreeTest.java b/src/test/java/CosmasTreeTest.java
index e16f8d8..0d7db7a 100644
--- a/src/test/java/CosmasTreeTest.java
+++ b/src/test/java/CosmasTreeTest.java
@@ -56,6 +56,16 @@
 		assertEquals(single3.replaceAll(" ", ""), map.replaceAll(" ", ""));
 	}
 	
+//	@Test
+	public void testMORPH() throws QueryException {
+		query="#MORPH(V)";
+		String morph1 = 
+					"{@type=korap:token, @value={@type=korap:term, @value=pos:v, relation==}}";
+		ppt = new CosmasTree(query);
+		map = ppt.getRequestMap().get("query").toString();
+		assertEquals(morph1.replaceAll(" ", ""), map.replaceAll(" ", ""));
+	}
+	
 	@Test
 	public void testSequence() throws QueryException {
 		query="der Mann";
@@ -281,7 +291,7 @@
 		String opin1 = 
 					"{@type=korap:group, relation=shrink, shrink=1, operands=[" +
 						"{@type=korap:group, relation=position, position=contains, operands=[" +
-							"{@type=korap:elem, @value=s}," +
+							"{@type=korap:element, @value=s}," +
 							"{@type=korap:group, class=1, operands=[" +
 								"{@type=korap:token, @value={@type=korap:term, @value=orth:wegen, relation==}}" +
 							"]}" +
@@ -295,7 +305,7 @@
 		String opin2 = 
 					"{@type=korap:group, relation=shrink, shrink=1, operands=[" +
 						"{@type=korap:group, relation=position, position=startswith, operands=[" +
-							"{@type=korap:elem, @value=s}," +
+							"{@type=korap:element, @value=s}," +
 							"{@type=korap:group, class=1, operands=[" +
 								"{@type=korap:token, @value={@type=korap:term, @value=orth:wegen, relation==}}" +
 							"]}" +
@@ -309,7 +319,7 @@
 		String opin3 = 
 					"{@type=korap:group, relation=shrink, shrink=1, operands=[" +
 						"{@type=korap:group, relation=position, position=startswith, @subtype=excl, operands=[" +
-							"{@type=korap:elem, @value=s}," +
+							"{@type=korap:element, @value=s}," +
 							"{@type=korap:group, class=1, operands=[" +
 								"{@type=korap:token, @value={@type=korap:term, @value=orth:wegen, relation==}}" +
 							"]}" +
@@ -323,7 +333,7 @@
 		String opin4 = 
 					"{@type=korap:group, relation=shrink, shrink=1, operands=[" +
 						"{@type=korap:group, relation=position, position=ident, range=all, @subtype=excl, grouping=false, operands=[" +
-							"{@type=korap:elem, @value=s}," +
+							"{@type=korap:element, @value=s}," +
 							"{@type=korap:group, class=1, operands=[" +
 								"{@type=korap:token, @value={@type=korap:term, @value=orth:wegen, relation==}}" +
 							"]}" +
@@ -340,7 +350,7 @@
 		String opov1 = 
 					"{@type=korap:group, relation=shrink, shrink=1, operands=[" +
 						"{@type=korap:group, relation=overlap, position=any, operands=[" +
-							"{@type=korap:elem, @value=s}," +
+							"{@type=korap:element, @value=s}," +
 							"{@type=korap:group, class=1, operands=[" +
 								"{@type=korap:token, @value={@type=korap:term, @value=orth:wegen, relation==}}" +
 							"]}" +
@@ -354,7 +364,7 @@
 		String opov2 = 
 					"{@type=korap:group, relation=shrink, shrink=1, operands=[" +
 						"{@type=korap:group, relation=overlap, position=startswith, operands=[" +
-							"{@type=korap:elem, @value=s}," +
+							"{@type=korap:element, @value=s}," +
 							"{@type=korap:group, class=1, operands=[" +
 								"{@type=korap:token, @value={@type=korap:term, @value=orth:wegen, relation==}}" +
 							"]}" +
@@ -440,7 +450,7 @@
 	public void testELEM() throws QueryException {
 		// http://www.ids-mannheim.de/cosmas2/web-app/hilfe/suchanfrage/eingabe-zeile/syntax/elem.html
 		query="#ELEM(S)";
-		String elem1 = "{@type=korap:elem, @value=s}";
+		String elem1 = "{@type=korap:element, @value=s}";
 		ppt = new CosmasTree(query);
 		map = ppt.getRequestMap().get("query").toString();
 		assertEquals(elem1.replaceAll(" ", ""), map.replaceAll(" ", ""));
@@ -487,7 +497,7 @@
 		query = "#BED(der , sa)";
 		String bed1 = 
 				"{@type=korap:group, relation=position, position=startswith, operands=[" +
-					"{@type=korap:elem, @value=s}," +
+					"{@type=korap:element, @value=s}," +
 					"{@type=korap:token, @value={@type=korap:term, @value=orth:der, relation==}}" +
 				"]}";
 		ppt = new CosmasTree(query);
@@ -497,7 +507,7 @@
 		query = "#BED(der Mann , +pe)";
 		String bed2 = 
 				"{@type=korap:group, relation=position, position=endswith, operands=[" +
-					"{@type=korap:elem, @value=p}," +
+					"{@type=korap:element, @value=p}," +
 					"{@type=korap:sequence, operands=[" +
 						"{@type=korap:token, @value={@type=korap:term, @value=orth:der, relation==}}," +
 						"{@type=korap:token, @value={@type=korap:term, @value=orth:Mann, relation==}}" +
@@ -511,14 +521,14 @@
 		String bed3 = 
 				"{@type=korap:group, relation=and, operands=[" +
 					"{@type=korap:group, relation=position, position=startswith, operands=[" +
-						"{@type=korap:elem, @value=s}," +
+						"{@type=korap:element, @value=s}," +
 						"{@type=korap:sequence, operands=[" +
 							"{@type=korap:token, @value={@type=korap:term, @value=orth:der, relation==}}," +
 							"{@type=korap:token, @value={@type=korap:term, @value=orth:Mann, relation==}}" +
 						"]}" +
 					"]}," +
 					"{@type=korap:group, relation=position, position=startswith, @subtype=excl, operands=[" +
-						"{@type=korap:elem, @value=p}," +
+						"{@type=korap:element, @value=p}," +
 						"{@type=korap:sequence, operands=[" +
 							"{@type=korap:token, @value={@type=korap:term, @value=orth:der, relation==}}," +
 							"{@type=korap:token, @value={@type=korap:term, @value=orth:Mann, relation==}}" +
diff --git a/src/test/java/PoliqarpPlusTreeTest.java b/src/test/java/PoliqarpPlusTreeTest.java
index 35753d6..5561d16 100644
--- a/src/test/java/PoliqarpPlusTreeTest.java
+++ b/src/test/java/PoliqarpPlusTreeTest.java
@@ -84,7 +84,7 @@
 				"{@type=korap:token, @value={@type=korap:term, @value=base:der, relation==}}," +
 				"{@type=korap:token, @value={@type=korap:term, @value=base:Mann, relation==}}" +
 			"]}";
-		ppt = new PoliqarpPlusTree("[base=der][][base=Mann]");
+		ppt = new PoliqarpPlusTree("[base=der][][][base=Mann]");
 		map = ppt.getRequestMap().get("query").toString();
 		assertEquals(et2.replaceAll(" ", ""), map.replaceAll(" ", ""));
 		
@@ -101,31 +101,36 @@
 		map = ppt.getRequestMap().get("query").toString();
 		assertEquals(et3.replaceAll(" ", ""), map.replaceAll(" ", ""));
 		
-		// [base=der][]*[base=Mann]
-		String et4 = 
-			"{@type=korap:group, relation=distance, @subtype=incl, constraint=[" +
-				"{@type=korap:distance, measure=w, direction=plus, min=0, max=INF}" +
-			"], " +
-			"operands=[" +
-				"{@type=korap:token, @value={@type=korap:term, @value=base:der, relation==}}," +
-				"{@type=korap:token, @value={@type=korap:term, @value=base:Mann, relation==}}" +
-			"]}";
-		ppt = new PoliqarpPlusTree("[base=der][]*[base=Mann]");
-		map = ppt.getRequestMap().get("query").toString();
-		assertEquals(et4.replaceAll(" ", ""), map.replaceAll(" ", ""));
 		
 		// startswith(<s>, [][base=Mann]
-		String et5 = 
-			"{@type=korap:group, relation=position, position=startswith, @subtype=incl, operands=[" +
-				"{@type=korap:token, @value={@type=korap:elem, @value=s}," +
-				"{@type=korap:sequence, offset=1, operands=[" +
+		String et4 = 
+			"{@type=korap:group, relation=position, position=startswith, operands=[" +
+				"{@type=korap:element, @value=s}," +
+				"{@type=korap:sequence, offset-min=1, offset-max=1, operands=[" +
 					"{@type=korap:token, @value={@type=korap:term, @value=base:Mann, relation==}}" +
 				"]}" +
 			"]}";
-		ppt = new PoliqarpPlusTree("startswith(<s>, [][base=Mann]");
+		ppt = new PoliqarpPlusTree("startswith(<s>, [][base=Mann])");
+		map = ppt.getRequestMap().get("query").toString();
+		assertEquals(et4.replaceAll(" ", ""), map.replaceAll(" ", ""));
+		
+		String et5 = 
+				"{@type=korap:group, relation=distance, @subtype=incl, constraint=[" +
+					"{@type=korap:distance, measure=w, direction=plus, min=1, max=1}" +
+				"], " +
+				"operands=[" +
+					"{@type=korap:token, @value={@type=korap:term, @value=base:der, relation==}}," +
+					"{@type=korap:group, relation=distance, @subtype=incl, constraint=[" +
+						"{@type=korap:distance, measure=w, direction=plus, min=2, max=2}" +
+					"], " +
+					"operands=[" +
+						"{@type=korap:token, @value={@type=korap:term, @value=base:Mann, relation==}}," +
+						"{@type=korap:token, @value={@type=korap:term, @value=base:Frau, relation==}}" +
+					"]}" +
+				"]}";
+		ppt = new PoliqarpPlusTree("[base=der][][base=Mann][][][base=Frau]");
 		map = ppt.getRequestMap().get("query").toString();
 		assertEquals(et5.replaceAll(" ", ""), map.replaceAll(" ", ""));
-
 		
 	}