cleanup, restructuring of n_ary_linguistic_term, multiple predications (almost complete)
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 4943874..5610d1c 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
@@ -95,6 +95,13 @@
 		return group;
 	}
 	
+	protected LinkedHashMap<String, Object> makeFocus(int classRef) {
+		LinkedHashMap<String, Object> group = new LinkedHashMap<String, Object>();
+		group.put("@type", "korap:focus");
+		group.put("classRef", classRef);
+		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 c64e702..4efeeb6 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
@@ -59,6 +59,7 @@
 	 * Keeps track of operands that are to be integrated into yet uncreated objects.
 	 */
 	LinkedList<LinkedHashMap<String,Object>> operandStack = new LinkedList<LinkedHashMap<String,Object>>();
+	
 	/**
 	 * Keeps track of explicitly (by #-var definition) or implicitly (number as reference) introduced entities (for later reference by #-operator)
 	 */
@@ -86,14 +87,25 @@
 	 */
 	int classCounter = 0;
 	/**
+	 * Keeps track of numers of relations processed (important when dealing with multiple predications).
+	 */
+	int relationCounter = 0;
+	/**
 	 * Keeps track of references to nodes that are operands of groups (e.g. tree relations). Those nodes appear on the top level of the parse tree
 	 * but are to be integrated into the AqlTree at a later point (namely as operands of the respective group). Therefore, store references to these
 	 * nodes here and exclude the operands from being written into the query map individually.   
 	 */
 	private LinkedList<String> operandOnlyNodeRefs = new LinkedList<String>();
+	
+	private LinkedList<Integer> establishedFoci = new LinkedList<Integer>();
+	private LinkedList<Integer> usedReferences = new LinkedList<Integer>();
 //	private List<String> mirroredPositionFrames = Arrays.asList(new String[]{"startswith", "endswith", "overlaps", "contains"});
 	private List<String> mirroredPositionFrames = Arrays.asList(new String[]{});
-	
+	List<ParseTree> globalLingTermNodes = new ArrayList<ParseTree>();
+	private int totalRelationCount;
+	private LinkedList<String> multiplyReferencedNodes = new LinkedList<String>();
+	private LinkedHashMap<String, Integer> nodeReferencesTotal = new LinkedHashMap<String, Integer>();
+	private LinkedHashMap<String, Integer> nodeReferencesProcessed = new LinkedHashMap<String, Integer>();
 	public static boolean verbose = false;
 	
 	/**
@@ -178,6 +190,8 @@
 			System.err.println(" "+objectStack);
 			System.out.println(openNodeCats);
 		}
+		
+		
 
 		/*
 		 ****************************************************************
@@ -203,7 +217,7 @@
 			// naturally as operands of the relations/groups introduced by the 
 			// *node. For that purpose, this section mines all used references
 			// and stores them in a list for later reference.
-			List<ParseTree> globalLingTermNodes = new ArrayList<ParseTree>();
+			
 			for (ParseTree exprNode : getChildrenWithCat(node,"expr")) {
 				// Pre-process any 'variableExpr' such that the variableReferences map can be filled
 				List<ParseTree> definitionNodes = new ArrayList<ParseTree>();
@@ -215,54 +229,27 @@
 				List<ParseTree> lingTermNodes = new ArrayList<ParseTree>();
 				lingTermNodes.addAll(getChildrenWithCat(exprNode, "n_ary_linguistic_term"));
 				globalLingTermNodes.addAll(lingTermNodes);
+				totalRelationCount  = globalLingTermNodes.size();
 				// Traverse refOrNode nodes under *ary_linguistic_term nodes and extract references
 				for (ParseTree lingTermNode : lingTermNodes) {
 					for (ParseTree refOrNode : getChildrenWithCat(lingTermNode, "refOrNode")) {
 						String refOrNodeString = refOrNode.getChild(0).toStringTree(parser);
 						if (refOrNodeString.startsWith("#")) {
-							operandOnlyNodeRefs.add(refOrNode.getChild(0).toStringTree(parser).substring(1));
-						} else {
-							
+							String ref = refOrNode.getChild(0).toStringTree(parser).substring(1);
+							if (nodeReferencesTotal.containsKey(ref)) {
+								nodeReferencesTotal.put(ref, nodeReferencesTotal.get(ref)+1);
+							} else {
+								nodeReferencesTotal.put(ref, 1);
+								nodeReferencesProcessed.put(ref, 0);
+							}
 						}
-						
 					}
 				}
 			}
-//			// TODO first check all 'expr' children for n_ary_linguistic_terms (see below)
-//			if (node.getChildCount() > 1) {
-//				LinkedHashMap<String, Object> andGroup = makeGroup("and");
-//				objectStack.push(andGroup);
-//				stackedObjects++;
-//				putIntoSuperObject(andGroup,1);
-//			}
-			if (globalLingTermNodes.size() > 1) {
-				LinkedHashMap<String, Object> zeroTextDistance = makeGroup("sequence");
-				ArrayList<Object> distances = new ArrayList<Object>();
-				distances.add(makeDistance("t",0,0));
-				zeroTextDistance.put("distances", distances);
-				putIntoSuperObject(zeroTextDistance);
-				objectStack.push(zeroTextDistance);
-//				stackedObjects++;
-			}
 		}
 		
 		// establish new variables or relations between vars
 		if (nodeCat.equals("expr")) {
-			// Check if expr node has one or more "n_ary_linguistic_term" nodes.
-			// Those nodes may use references to earlier established operand nodes.
-			// Those operand nodes are not to be included into the query map individually but
-			// naturally as operands of the relations/groups introduced by the 
-			// n_ary_linguistic_term node. For that purpose, this section mines all used references
-			// and stores them in a list for later reference.
-//			List<ParseTree> lingTermNodes = new ArrayList<ParseTree>();
-//			lingTermNodes.addAll(getChildrenWithCat(node, "unary_linguistic_term"));
-//			lingTermNodes.addAll(getChildrenWithCat(node, "n_ary_linguistic_term"));
-//			// Traverse refOrNode nodes under *ary_linguistic_term nodes and extract references
-//			for (ParseTree lingTermNode : lingTermNodes) {
-//				for (ParseTree refOrNode : getChildrenWithCat(lingTermNode, "refOrNode")) {
-//					operandOnlyNodeRefs.add(refOrNode.getChild(0).toStringTree(parser).substring(1));
-//				}
-//			}
 		}
 		
 		if (nodeCat.equals("unary_linguistic_term")) {
@@ -273,114 +260,104 @@
 		}
 		
 		if (nodeCat.equals("n_ary_linguistic_term")) {
+			relationCounter++;
 			// get operator and determine type of group (sequence/treeRelation/relation/...)
 			// It's possible in Annis QL to concatenate operators, so there may be several operators under one n_ary_linguistic_term node. 
-			// Counter 'i' will point to all operator nodes (odd-numbered) under this node.
+			// Counter 'i' will iteratively point to all operator nodes (odd-numbered) under this node.
 			for (int i=1; i<node.getChildCount(); i = i+2) {
-				ParseTree operand1 = node.getChild(i-1);
-				ParseTree operand2 = node.getChild(i+1);
-				LinkedHashMap<String, Object> operatorTree = parseOperatorNode(node.getChild(i).getChild(0));
+				ParseTree operandTree1 = node.getChild(i-1);
+				ParseTree operandTree2 = node.getChild(i+1);
+				
+				LinkedHashMap<String, Object> operatorGroup = parseOperatorNode(node.getChild(i).getChild(0));
 				String groupType;
 				try {
-					groupType = (String) operatorTree.get("groupType");
+					groupType = (String) operatorGroup.get("groupType");
 				} catch (ClassCastException | NullPointerException n) {
 					groupType = "relation";
 				}
-				LinkedHashMap<String, Object> group;
-				List<Object> operands;
-				if (i == node.getChildCount()-2) {
-					group = makeGroup(groupType);
-					if (groupType.equals("relation") || groupType.equals("treeRelation")) {
-						LinkedHashMap<String, Object> relationGroup = new LinkedHashMap<String, Object>();
-						putAllButGroupType(relationGroup, operatorTree);
-						group.put("relation", relationGroup);
-					} else if (groupType.equals("sequence")) {
-						putAllButGroupType(group, operatorTree);
-					} else if (groupType.equals("position")) {
-						putAllButGroupType(group, operatorTree);
-					}
-					// insert referenced nodes into operands list
-					operands = (List<Object>) group.get("operands");
-				} else {
-					group = makeGroup("submatch");
-					ArrayList<Integer> classRef = new ArrayList<Integer>();
-					classRef.add(classCounter);
-					LinkedHashMap<String, Object> actualGroup = makeGroup(groupType);
-					group.put("classRef", classRef);
-					((ArrayList<Object>) group.get("operands")).add(actualGroup);
-					if (groupType.equals("relation") || groupType.equals("treeRelation")) {
-						LinkedHashMap<String, Object> relationGroup = new LinkedHashMap<String, Object>();
-						putAllButGroupType(relationGroup, operatorTree);
-						actualGroup.put("relation", relationGroup);
-					} else if (groupType.equals("sequence")) {
-						putAllButGroupType(actualGroup, operatorTree);
-					} else if (groupType.equals("position")) {
-						putAllButGroupType(actualGroup, operatorTree);
-					}
-					operands = (List<Object>) actualGroup.get("operands");
+				LinkedHashMap<String, Object> group = makeGroup(groupType);
+				if (groupType.equals("relation") || groupType.equals("treeRelation")) {
+					LinkedHashMap<String, Object> relationGroup = new LinkedHashMap<String, Object>();
+					putAllButGroupType(relationGroup, operatorGroup);
+					group.put("relation", relationGroup);
+				} else if (groupType.equals("sequence") || groupType.equals("position")) {
+					putAllButGroupType(group, operatorGroup);
 				}
+				// Get operands list before possible re-assignment of 'group' (see following 'if')
+				ArrayList<Object> operands  = (ArrayList<Object>) group.get("operands");
+				// Wrap in focus object in case other relations are following
+				if (i < node.getChildCount()-2) {
+					group = wrapInFocus(group);
+				}
+				// Retrieve operands.
+				String ref1 = null;
+				String ref2 = null;
+				LinkedHashMap<String, Object> operand1 = null;
+				LinkedHashMap<String, Object> operand2 = null;
+				if (!getNodeCat(operandTree1.getChild(0)).equals("variableExpr")) {
+					ref1 = operandTree1.getChild(0).toStringTree(parser).substring(1);
+					operand1 = variableReferences.get(ref1);
+					if (nodeReferencesProcessed.get(ref1) < nodeReferencesTotal.get(ref1)-1) {
+						operand1 = wrapInClass(operand1);
+						group = wrapInFocus(group);
+						classCounter++;
+						nodeReferencesProcessed.put(ref1, nodeReferencesProcessed.get(ref1)+1);
+					}
+				}
+				if (!getNodeCat(operandTree2.getChild(0)).equals("variableExpr")) {
+					ref2 = operandTree2.getChild(0).toStringTree(parser).substring(1);
+					operand2 = variableReferences.get(ref2);
+					if (nodeReferencesProcessed.get(ref2) < nodeReferencesTotal.get(ref2)-1) {
+						operand2 = wrapInClass(operand2);
+						group = wrapInFocus(group);
+						classCounter++;
+						nodeReferencesProcessed.put(ref2, nodeReferencesProcessed.get(ref2)+1);
+					}
+				}
+				// XXX deal with multiple predications
 				
+				// Inject operands.
 				// -> Case distinction:
-				// Things are easy when there's just one operator (thus 3 children incl. operands)...				
 				if (node.getChildCount()==3) {
-					if (!getNodeCat(operand1.getChild(0)).equals("variableExpr")) {
-						String ref1 = operand1.getChild(0).toStringTree(parser).substring(1);
-						operands.add(variableReferences.get(ref1));
-					}
-					if (!getNodeCat(operand2.getChild(0)).equals("variableExpr")) {
-						String ref2 = operand2.getChild(0).toStringTree(parser).substring(1);
-						operands.add(variableReferences.get(ref2));
-					}
-					putIntoSuperObject(group);
-					objectStack.push(group);
-					stackedObjects++;
-				// ...but stuff gets a little more complicated here. The AST is of this form: (operand1 operator 1 operand2 operator2 operand3 operator3 ...)
-				// but we'll have to serialize it in a nested, binary way: (((operand1 operator1 operand2) operator2 operand3) operator3 ...)
-				// the following code will do just that:
-				} else { 
+					System.err.println("foo");
+					// Things are easy when there's just one operator (thus 3 children incl. operands)...
+					if (operand1 != null) operands.add(operand1);
+					if (operand2 != null) operands.add(operand2);
+				} else {
+					// ... but things get a little more complicated here. The AST is of this form: (operand1 operator 1 operand2 operator2 operand3 operator3 ...)
+					// but we'll have to serialize it in a nested, binary way: (((operand1 operator1 operand2) operator2 operand3) operator3 ...)
+					// the following code will do just that:
 					// for the first operator, include both operands
 					if (i == 1) {
-						if (!getNodeCat(operand1.getChild(0)).equals("variableExpr")) {
-							String ref1 = operand1.getChild(0).toStringTree(parser).substring(1);
-							operands.add(variableReferences.get(ref1));
-						}
-						if (!getNodeCat(operand2.getChild(0)).equals("variableExpr")) {
-							String ref2= operand2.getChild(0).toStringTree(parser).substring(1);
-							LinkedHashMap<String, Object> classGroup = makeClass(classCounter);
-							((ArrayList<Object>) classGroup.get("operands")).add(variableReferences.get(ref2));
-							operands.add(classGroup);
-							classCounter++;
-						}
+						if (operand1 != null) operands.add(operand1);
+						if (operand2 != null) operands.add(wrapInClass(operand2));
+						classCounter++;
 						// Don't put this into the super object directly but store on operandStack 
 						// (because this group will have to be an operand of a subsequent operator)
 						operandStack.push(group);
 					// for all subsequent operators, only take the 2nd operand (first was already added by previous operator)
 					// This is the last operator. Include 2nd operand and insert previously stored group at first position
 					} else if (i == node.getChildCount()-2) {
-						if (!getNodeCat(operand2.getChild(0)).equals("variableExpr")) {
-							String ref2 = operand2.getChild(0).toStringTree(parser).substring(1);
-							operands.add(variableReferences.get(ref2));
-						}
-						putIntoSuperObject(group);
-						if (!operandStack.isEmpty()) {
-							operands.add(0, operandStack.pop());
-							operandStack.clear();
-						}
-						objectStack.push(group);
-						stackedObjects++;
+						if (operand2 != null) operands.add(operand2);
 					// for all intermediate operators, include other previous groups and 2nd operand. Store this on the operandStack, too.
 					} else {
-						if (!getNodeCat(operand2.getChild(0)).equals("variableExpr")) {
-							String ref2 = operand2.getChild(0).toStringTree(parser).substring(1);
-							LinkedHashMap<String, Object> classGroup = makeClass(classCounter);
-							((ArrayList<Object>) classGroup.get("operands")).add(variableReferences.get(ref2));
-							operands.add(classGroup);
-							classCounter++;
-						}
+						if (operand2 != null) operands.add(wrapInClass(operand2));
+						classCounter++;
 						operands.add(0, operandStack.pop());
 						operandStack.push(group);
 					}
 				}
+				if (i == node.getChildCount()-2 && relationCounter == totalRelationCount) {
+					putIntoSuperObject(group);
+					if (!operandStack.isEmpty()) {
+						operands.add(0, operandStack.pop());
+						operandStack.clear();
+					}
+					objectStack.push(group);
+					stackedObjects++;
+				} else {
+					operandStack.push(group);
+				}
 			}
 		}
 		
@@ -462,6 +439,24 @@
 	}
 
 
+	@SuppressWarnings("unchecked")
+	private LinkedHashMap<String, Object> wrapInFocus(
+			LinkedHashMap<String, Object> group) {
+		LinkedHashMap<String, Object> focusGroup = makeGroup("focus");
+		((ArrayList<Object>) focusGroup.get("operands")).add(group);
+		ArrayList<Integer> classRefs = new ArrayList<Integer>();
+		classRefs.add(classCounter);
+		focusGroup.put("classRef", classRefs);
+		return focusGroup;
+	}
+
+	@SuppressWarnings("unchecked")
+	private LinkedHashMap<String, Object> wrapInClass(LinkedHashMap<String, Object> object) {
+		LinkedHashMap<String, Object> group = makeClass(classCounter);
+		((ArrayList<Object>) group.get("operands")).add(object);
+		return group;
+	}
+
 	/**
 	 * Parses a unary_linguistic_operator node. Possible operators are: root, arity, tokenarity.
 	 * Operators are embedded into a korap:term, in turn wrapped by an 'attr' property in a korap:span.
@@ -699,24 +694,25 @@
 	
 	@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");
 			if (!invertedOperandsLists.contains(topObjectOperands)) {
 				topObjectOperands.add(object);
 			} else {
 				topObjectOperands.add(0, object);
 			}
-			
 		} else {
 			requestMap.put("query", object);
 		}
 	}
+
+	@SuppressWarnings("unchecked")
+	private void putGroupAndWrapFocus(LinkedHashMap<String, Object> thisObject, LinkedHashMap<String, Object> formerObject, int focusClass) {
+		LinkedHashMap<String, Object> focusWrap = makeGroup("focus");
+		focusWrap.put("classRef", focusClass);
+		((ArrayList<Object>) focusWrap.get("operands")).add(formerObject);
+		((ArrayList<Object>) thisObject.get("operands")).add(focusWrap);
+	}
 	
 	private void putAllButGroupType(Map<String, Object> container, Map<String, Object> input) {
 		for (String key : input.keySet()) {
@@ -767,18 +763,20 @@
 		 * For testing
 		 */
 		String[] queries = new String[] {
-			 "node & #1:root",
-			 "pos=\"N\" & pos=\"V\" & pos=\"N\" & #1 . #2 & #2 . #3",
-			 "cat=\"NP\" & #1:tokenarity=2",
-			 "node & node & node & #1 . #2 . #3",
-			 "cat=\"CP\" & cat=\"VP\" & cat=\"NP\" & #1 > #2 > #3",
-			 "cat=\"CP\" & cat=\"VP\" & cat=\"NP\" & cat=\"DP\" & #1 > #2 > #3 > #4",
-			 "pos=\"N\" & pos=\"V\" & pos=\"P\" & #1 . #2 & #2 . #3"
+//			 "node & #1:root",
+//			 "pos=\"N\" & pos=\"V\" & pos=\"N\" & #1 . #2 & #2 . #3",
+//			 "cat=\"NP\" & #1:tokenarity=2",
+//			 "node & node & node & #1 . #2 . #3",
+//			 "cat=\"CP\" & cat=\"VP\" & cat=\"NP\" & #1 > #2 > #3",
+//			 "cat=\"CP\" & cat=\"VP\" & cat=\"NP\" & cat=\"DP\" & #1 > #2 > #3 > #4",
+//			 "pos=\"N\" & pos=\"V\" & pos=\"P\" & #1 . #2 & #2 . #3"
 //			 "cnx/cat=\"NP\" > node",
 //			 "node > node",
 //			 "cat=/NP/ > node",
 //			 "/Mann/",
 //			 "node > tok=\"foo\"",
+				"tok=\"Sonne\" & tok=\"Mond\" & #1 > #2 .0,4  tok=\"Sterne\"",
+				 "pos=\"N\" & pos=\"V\" & pos=\"P\" & #1 . #2 & #2 . #3"
 			};
 		AqlTree.verbose=true;
 		for (String q : queries) {
diff --git a/src/test/java/AqlTreeTest.java b/src/test/java/AqlTreeTest.java
index fc4847f..0bac98e 100644
--- a/src/test/java/AqlTreeTest.java
+++ b/src/test/java/AqlTreeTest.java
@@ -181,7 +181,7 @@
 		query = "cat=\"CP\" & cat=\"VP\" & cat=\"NP\" & #1 > #2 > #3";
 		String dom1 = 
 				"{@type=korap:group, operation=operation:relation, operands=[" +
-						"{@type=korap:group, operation=operation:submatch, operands=[" +
+						"{@type=korap:group, operation=operation:focus, operands=[" +
 							"{@type=korap:group, operation=operation:relation, operands=[" +
 								"{@type=korap:span, layer=cat, key=CP, match=match:eq}," +
 								"{@type=korap:group, operation=operation:class, class=0, operands=[" +
@@ -199,9 +199,9 @@
 		query = "cat=\"CP\" & cat=\"VP\" & cat=\"NP\" & cat=\"DP\" & #1 > #2 > #3 > #4";
 		String dom2 = 
 				"{@type=korap:group, operation=operation:relation, operands=[" +
-						"{@type=korap:group, operation=operation:submatch, operands=[" +
+						"{@type=korap:group, operation=operation:focus, operands=[" +
 							"{@type=korap:group, operation=operation:relation, operands=[" +
-								"{@type=korap:group, operation=operation:submatch, operands=[" +
+								"{@type=korap:group, operation=operation:focus, operands=[" +
 									"{@type=korap:group, operation=operation:relation, operands=[" +
 										"{@type=korap:span, layer=cat, key=CP, match=match:eq}," +
 										"{@type=korap:group, operation=operation:class, class=0, operands=[" +
@@ -295,7 +295,7 @@
 		String seq4 = 
 				"{@type=korap:group, operation=operation:sequence," +
 					"operands=[" +
-						"{@type=korap:group, operation=operation:submatch, operands=[" +
+						"{@type=korap:group, operation=operation:focus, operands=[" +
 							"{@type=korap:group, operation=operation:sequence, operands=[" +
 								"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=Sonne, match=match:eq}}," +
 								"{@type=korap:group, operation=operation:class, class=0, operands=[" +
@@ -317,7 +317,7 @@
 		query = "node & node & node & #1 . #2 .1,3 #3";
 		String seq5 = 
 				"{@type=korap:group, operation=operation:sequence, operands=[" +
-						"{@type=korap:group, operation=operation:submatch, operands=[" +
+						"{@type=korap:group, operation=operation:focus, operands=[" +
 							"{@type=korap:group, operation=operation:sequence, operands=[" +
 								"{@type=korap:span}," +
 								"{@type=korap:group, operation=operation:class, class=0, operands=[" +
@@ -340,7 +340,7 @@
 		query = "tok=\"Sonne\" & tok=\"Mond\" & tok=\"Sterne\" & #1 > #2 .0,4 #3";
 		String seq4 = 
 					"{@type=korap:group, operation=operation:sequence, operands=[" +
-							"{@type=korap:group, operation=operation:submatch, operands=[" +
+							"{@type=korap:group, operation=operation:focus, operands=[" +
 									"{@type=korap:group, operation=operation:relation, operands=[" +
 										"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=Sonne, match=match:eq}}," +
 										"{@type=korap:group, operation=operation:class, class=0, operands=[" +
@@ -360,7 +360,7 @@
 		query = "tok=\"Sonne\" & tok=\"Mond\" & #1 > #2 .0,4  tok=\"Sterne\"";
 		String seq5 = 
 					"{@type=korap:group, operation=operation:sequence, operands=[" +
-							"{@type=korap:group, operation=operation:submatch, operands=[" +
+							"{@type=korap:group, operation=operation:focus, operands=[" +
 									"{@type=korap:group, operation=operation:relation, operands=[" +
 										"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=Sonne, match=match:eq}}," +
 										"{@type=korap:group, operation=operation:class, class=0, operands=[" +
@@ -438,25 +438,41 @@
 	
 	@Test
 	public void testMultiplePredications() throws QueryException {
-		// a noun before a verb before a noun
-		// XXX Warning incorrect serialisation! Need to ensure that the two Vs are identical! 
-		// Embed in one sequence!
+		// a noun before a verb before a preposition
 		query = "pos=\"N\" & pos=\"V\" & pos=\"P\" & #1 . #2 & #2 . #3"; 
 		String mult1 = 
+		"{@type=korap:group, operation=operation:sequence, operands=[" +
+			"{@type=korap:group, operation=operation:focus, operands=[" +
 				"{@type=korap:group, operation=operation:sequence, operands=[" +
-					"{@type=korap:group, operation=operation:submatch, operands=[" +
-						"{@type=korap:group, operation=operation:sequence, operands=[" +
-							"{@type=korap:token, wrap={@type=korap:term, layer=pos, key=N, match=match:eq}}," +
-							"{@type=korap:group, operation=operation:class, class=0, operands=[" +
-								"{@type=korap:token, wrap={@type=korap:term, layer=pos, key=V, match=match:eq}}" +
-							"]}" +
-						"], inOrder=true}" +
-					"], classRef=[0]}," +
-					"{@type=korap:token, wrap={@type=korap:term, layer=pos, key=P, match=match:eq}}" +
-				"]}";
+					"{@type=korap:token, wrap={@type=korap:term, layer=pos, key=N, match=match:eq}}," +
+					"{@type=korap:group, operation=operation:class, class=0, operands=[" +
+						"{@type=korap:token, wrap={@type=korap:term, layer=pos, key=V, match=match:eq}}" +
+					"]}" +
+				"], inOrder=true}" +
+			"], classRef=[0]}," +
+			"{@type=korap:token, wrap={@type=korap:term, layer=pos, key=P, match=match:eq}}" +
+		"], inOrder=true}";
 		aqlt = new AqlTree(query);
 		map = aqlt.getRequestMap().get("query").toString();
 		assertEquals(mult1.replaceAll(" ", ""), map.replaceAll(" ", ""));
+		
+		// a noun before a verb before a preposition
+		query = "pos=\"N\" & pos=\"V\" & #1 . #2 & #2 . pos=\"P\""; 
+		String mult2 = 
+		"{@type=korap:group, operation=operation:sequence, operands=[" +
+			"{@type=korap:group, operation=operation:focus, operands=[" +
+				"{@type=korap:group, operation=operation:sequence, operands=[" +
+					"{@type=korap:token, wrap={@type=korap:term, layer=pos, key=N, match=match:eq}}," +
+					"{@type=korap:group, operation=operation:class, class=0, operands=[" +
+						"{@type=korap:token, wrap={@type=korap:term, layer=pos, key=V, match=match:eq}}" +
+					"]}" +
+				"], inOrder=true}" +
+			"], classRef=[0]}," +
+			"{@type=korap:token, wrap={@type=korap:term, layer=pos, key=P, match=match:eq}}" +
+		"], inOrder=true}";
+		aqlt = new AqlTree(query);
+		map = aqlt.getRequestMap().get("query").toString();
+		assertEquals(mult2.replaceAll(" ", ""), map.replaceAll(" ", ""));
 	}	
 	
 	@Test