opbed and opnhit adjusted to specs
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 366577a..49be6a0 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
@@ -335,34 +335,25 @@
 			proxSequence.put("operation", "operation:"+ "sequence");
 			objectStack.push(proxSequence);
 			stackedObjects++;
-//			if (openNodeCats.get(1).equals("OPALL")) proxSequence.put("match", "match:"+"all");
-//			else if (openNodeCats.get(1).equals("OPNHIT")) proxSequence.put("match", "match:"+"between");
-//			else proxSequence.put("match", "match:"+"operands");
 			ArrayList<Object> constraints = new ArrayList<Object>();
 			boolean exclusion = ! typ.getChild(0).toStringTree().equals("PROX"); 
 			
-			boolean inOrder = true;
+			boolean inOrder = false;
 			proxSequence.put("inOrder", inOrder);
 			proxSequence.put("distances", constraints);
 			
 			ArrayList<Object> operands = new ArrayList<Object>(); 
 			proxSequence.put("operands", operands);
-			
-			// if only one dist_info, put directly into constraints
-			if (dist_list.getChildCount()==1) {
-				String direction = dist_list.getChild(0).getChild(0).getChild(0).toStringTree().toLowerCase();
-				String min = dist_list.getChild(0).getChild(1).getChild(0).toStringTree();
-				String max = dist_list.getChild(0).getChild(1).getChild(1).toStringTree();
-				String meas = dist_list.getChild(0).getChild(2).getChild(0).toStringTree();
+		
+			// possibly several distance constraints
+			for (int i=0; i<dist_list.getChildCount(); i++) {
+				String direction = dist_list.getChild(i).getChild(0).getChild(0).toStringTree().toLowerCase();
+				String min = dist_list.getChild(i).getChild(1).getChild(0).toStringTree();
+				String max = dist_list.getChild(i).getChild(1).getChild(1).toStringTree();
+				String meas = dist_list.getChild(i).getChild(2).getChild(0).toStringTree();
 				if (min.equals("VAL0")) {
 					min="0";
 				}
-				if (direction.equals("minus")) {
-					direction = "plus";
-					invertedOperandsLists.add(operands);
-				} else if (direction.equals("both")) {
-					inOrder=false;
-				}
 				LinkedHashMap<String, Object> distance = new LinkedHashMap<String, Object>();
 				distance.put("@type", "korap:distance");
 				distance.put("key", meas);
@@ -372,43 +363,14 @@
 					distance.put("exclude", exclusion);
 				}
 				constraints.add(distance);
-				proxSequence.put("inOrder", inOrder);
-			}
-			
-			// otherwise, create group and add info there
-			else {
-				LinkedHashMap<String, Object> distanceGroup = new LinkedHashMap<String, Object>();
-				ArrayList<Object> groupOperands = new ArrayList<Object>();
-				distanceGroup.put("@type", "korap:group");
-				distanceGroup.put("operation", "operation:"+ "and");
-				distanceGroup.put("operands", groupOperands);
-//				constraints.add(distanceGroup);
-				for (int i=0; i<dist_list.getChildCount(); i++) {
-					String direction = dist_list.getChild(i).getChild(0).getChild(0).toStringTree().toLowerCase();
-					String min = dist_list.getChild(i).getChild(1).getChild(0).toStringTree();
-					String max = dist_list.getChild(i).getChild(1).getChild(1).toStringTree();
-					String meas = dist_list.getChild(i).getChild(2).getChild(0).toStringTree();
-					if (min.equals("VAL0")) {
-						min=max;
-					}
-					LinkedHashMap<String, Object> distance = new LinkedHashMap<String, Object>();
-					distance.put("@type", "korap:distance");
-					distance.put("key", meas);
-					distance.put("min", Integer.parseInt(min));
-					distance.put("max", Integer.parseInt(max));
-					if (exclusion) {
-						distance.put("exclude", exclusion);
-					}
-					constraints.add(distance);
-					if (direction.equals("plus")) {
-						inOrder=true;
-					} else if (direction.equals("minus")) {
-						inOrder=true;
-						invertedOperandsLists.add(operands);
-					}
+				if (direction.equals("plus")) {
+					inOrder=true;
+				} else if (direction.equals("minus")) {
+					inOrder=true;
+					invertedOperandsLists.add(operands);
 				}
-				proxSequence.put("inOrder", inOrder);
 			}
+			proxSequence.put("inOrder", inOrder);
 			// Step II: decide where to put
 			putIntoSuperObject(proxSequence, 1);
 		}
@@ -447,7 +409,7 @@
 		
 		
 		// Wrap the first argument of an #IN operator in a class group
-		if (nodeCat.equals("ARG1") && (openNodeCats.get(1).equals("OPIN") || openNodeCats.get(1).equals("OPOV"))) {
+		if (nodeCat.equals("ARG1") && (openNodeCats.get(1).equals("OPIN") || openNodeCats.get(1).equals("OPOV") || openNodeCats.get(2).equals("OPNHIT"))) {
 			// Step I: create group
 			LinkedHashMap<String, Object> classGroup = new LinkedHashMap<String, Object>();
 			classGroup.put("@type", "korap:group");
@@ -460,12 +422,25 @@
 			putIntoSuperObject(classGroup, 1);
 		}
 		
+		// Wrap the 2nd argument of an #IN operator embedded in NHIT in a class group
+		if (nodeCat.equals("ARG2") && openNodeCats.get(2).equals("OPNHIT")) {
+			// Step I: create group
+			LinkedHashMap<String, Object> classGroup = new LinkedHashMap<String, Object>();
+			classGroup.put("@type", "korap:group");
+			classGroup.put("operation", "operation:"+ "class");
+			classGroup.put("class", 2);
+			classGroup.put("operands", new ArrayList<Object>());
+			objectStack.push(classGroup);
+			stackedObjects++;
+			// Step II: decide where to put
+			putIntoSuperObject(classGroup, 1);
+		}
+		
 		
 		if (nodeCat.equals("OPNHIT")) {
-//			proxGroupMatching = nodeCat.equals("OPALL") ? "all" : "exclude";
 			LinkedHashMap<String, Object> exclGroup = new LinkedHashMap<String, Object>();
 			exclGroup.put("@type", "korap:group");
-			exclGroup.put("operation", "operation:"+ "shrink");
+			exclGroup.put("operation", "operation:"+ "submatch");
 			ArrayList<Integer> classRef = new ArrayList<Integer>();
 			classRef.add(1);
 			classRef.add(2);
@@ -502,19 +477,21 @@
 			// Step I: create group
 			int optsChild = node.getChildCount()-1;
 			Tree conditions = node.getChild(optsChild).getChild(0);
+			
+			// create a containing group expressing the submatch constraint on the first argument
+			LinkedHashMap<String, Object> submatchgroup = new LinkedHashMap<String, Object>();
+			submatchgroup.put("@type", "korap:group");
+			submatchgroup.put("operation", "operation:"+ "submatch");
+			ArrayList<Integer> spanRef = new ArrayList<Integer>();
+			spanRef.add(1);
+			submatchgroup.put("classRef", spanRef);
+			ArrayList<Object> submatchoperands = new ArrayList<Object>();
+			submatchgroup.put("operands", submatchoperands);
+			putIntoSuperObject(submatchgroup, 1);
+			
 			// Distinguish two cases. Normal case: query has just one condition, like #BED(X, sa) ...
 			if (conditions.getChildCount()==1) {
 				CosmasCondition c = new CosmasCondition(conditions.getChild(0));
-				 
-				// create a containing group expressing the submatch constraint on the first argument
-				LinkedHashMap<String, Object> submatchgroup = new LinkedHashMap<String, Object>();
-				submatchgroup.put("@type", "korap:group");
-				submatchgroup.put("operation", "operation:"+ "submatch");
-				ArrayList<Integer> spanRef = new ArrayList<Integer>();
-				spanRef.add(1);
-				submatchgroup.put("classRef", spanRef);
-				ArrayList<Object> submatchoperands = new ArrayList<Object>();
-				submatchgroup.put("operands", submatchoperands);
 				
 				// create the group expressing the position constraint
 				LinkedHashMap<String, Object> posgroup = new LinkedHashMap<String, Object>();
@@ -543,47 +520,63 @@
 				operands.add(classGroup);
 				// Step II: decide where to put
 				submatchoperands.add(posgroup);
-				putIntoSuperObject(submatchgroup, 1);
+				
 			// ... or the query has several conditions specified, like #BED(XY, sa,-pa). In that case,
 			//     create an 'and' group and embed the position groups in its operands
 			} else {
 				// node has several conditions (like 'sa, -pa')
-				// -> create 'and' group and embed all position groups there
+				// -> create zero-distance sequence group and embed all position groups there
 				LinkedHashMap<String, Object> conjunct = new LinkedHashMap<String, Object>();
 				conjunct.put("@type", "korap:group");
-				conjunct.put("operation", "operation:"+ "and");
+				conjunct.put("operation", "operation:"+ "sequence");
+				ArrayList<Object> distances = new ArrayList<Object>();
+				conjunct.put("distances", distances);
+				LinkedHashMap<String, Object> zerodistance = new LinkedHashMap<String, Object>();
+				zerodistance.put("@type", "korap:distance");
+				zerodistance.put("key", "w");
+				zerodistance.put("min", 0);
+				zerodistance.put("max", 0);
+				distances.add(zerodistance);
 				ArrayList<Object> operands = new ArrayList<Object>();
 				conjunct.put("operands", operands);
 				ArrayList<ArrayList<Object>> distributedOperands = new ArrayList<ArrayList<Object>>();
 				
 				for (int i=0; i<conditions.getChildCount(); i++) {
-					// for each condition, create a position group. problem: how to get argument into every operands list?
+					// for each condition, create a position group containing a class group. problem: how to get argument into every operands list?
 					// -> use distributedOperandsLists
 					LinkedHashMap<String, Object> posGroup = new LinkedHashMap<String, Object>();
 					operands.add(posGroup);
 					
+					// make position group
 					CosmasCondition c = new CosmasCondition(conditions.getChild(i));
 					posGroup.put("@type", "korap:group");
 					posGroup.put("operation", "operation:"+ "position");
 					posGroup.put("frame", "frame:"+c.position);
 					if (c.negated) posGroup.put("exclude", "true");
 					ArrayList<Object> posOperands = new ArrayList<Object>();
-					distributedOperands.add(posOperands);
+					
+					// make class group 
+					LinkedHashMap<String, Object> classGroup = new LinkedHashMap<String, Object>();
+					classGroup.put("@type", "korap:group");
+					classGroup.put("operation", "operation:class");
+					classGroup.put("class", 1);
+					ArrayList<Object> classOperands = new ArrayList<Object>(); 
+					classGroup.put("operands", classOperands);
+					distributedOperands.add(classOperands);  // subtree to be put into every class group -> distribute
+					
+					// put the span and the class group into the position group
 					posGroup.put("operands", posOperands);
-					LinkedHashMap<String, Object> bedElem = new LinkedHashMap<String, Object>();
-					posOperands.add(bedElem);
-					bedElem.put("@type", "korap:span");
-					bedElem.put("key", c.elem);
-					
-					
+					LinkedHashMap<String, Object> span = new LinkedHashMap<String, Object>();
+					posOperands.add(span);
+					posOperands.add(classGroup);
+					span.put("@type", "korap:span");
+					span.put("key", c.elem);
 				}
-				putIntoSuperObject(conjunct, 0);
+				submatchoperands.add(conjunct);
 				distributedOperandsLists.push(distributedOperands);
 			}
-
+			
 		}
-		
-		
 		objectsToPop.push(stackedObjects);
 		
 		/*
@@ -695,7 +688,7 @@
 	}
 
 	/**
-	 * Translates the text area specifications (position option arguments) to terms used in serealisation.
+	 * Translates the text area specifications (position option arguments) to terms used in serialisation.
 	 * For the allowed argument types and their values for OPIN and OPOV, see
 	 * http://www.ids-mannheim.de/cosmas2/win-app/hilfe/suchanfrage/eingabe-grafisch/syntax/ARGUMENT_I.html or
 	 * http://www.ids-mannheim.de/cosmas2/win-app/hilfe/suchanfrage/eingabe-grafisch/syntax/ARGUMENT_O.html, respectively.
@@ -790,18 +783,7 @@
 //				"#BEG(der /w3:5 Mann) /+w10 kommt",
 //				"&würde /w0 MORPH(V)",
 				"#NHIT(gehen /w1:10 voran)",
-				"Der Mann",
-				"Der /+w1:3 Mann",
-				"Der /+w1:3,s1 Mann",
-				"(Der /+w1:3,s1 Mann) /+w5 geht",
-				"(Der /+w1:3,s1 Mann) /-w5 geht",
-				"(Der /+w1:3,s1 Mann) /+w5 (geht weg)",
-				"Tag der $offenen Tür",
-				"#BED($wegen , sa)",
-				"#BEG(#ELEM(S))",
-				"#BEG(<s>)",
-				"MORPH(V PRES)",
-				"Mond?"
+				"#BED(der Mann , sa,-pa)"
 				};
 		CosmasTree.debug=true;
 		for (String q : queries) {
diff --git a/src/test/java/CosmasTreeTest.java b/src/test/java/CosmasTreeTest.java
index 03f3c76..1a350ea 100644
--- a/src/test/java/CosmasTreeTest.java
+++ b/src/test/java/CosmasTreeTest.java
@@ -505,19 +505,25 @@
 		assertEquals(all1.replaceAll(" ", ""), map.replaceAll(" ", ""));
 	}
 	
-//	@Test
+	@Test
 	public void testOPNHIT() throws QueryException {
 		query="#NHIT(gehen /w1:10 voran)";
 		String nhit1 = 
-				"{@type=korap:group, operation=operation:sequence, inOrder=false, " +
-					"distances=[" +
-						"{@type=korap:distance, key=w, min=1, max=10}" +
-					"], " +
-					"operands=[" +
-						"{@type=korap:token, wrap={@type=korap:term, key=gehen, layer=orth, match=match:eq}}," +
-						"{@type=korap:token, wrap={@type=korap:term, key=voran, layer=orth, match=match:eq}}" +
-					"]" +
-				"}";
+				"{@type=korap:group, operation=operation:submatch, classRef=[1,2], classRefOp=classRefOp:intersection, operands=[" +
+					"{@type=korap:group, operation=operation:sequence, inOrder=false, " +
+						"distances=[" +
+							"{@type=korap:distance, key=w, min=1, max=10}" +
+						"], " +
+						"operands=[" +
+							"{@type=korap:group, operation=operation:class, class=1, operands=[" +
+								"{@type=korap:token, wrap={@type=korap:term, key=gehen, layer=orth, match=match:eq}}" +
+							"]}," +
+							"{@type=korap:group, operation=operation:class, class=2, operands=[" +
+								"{@type=korap:token, wrap={@type=korap:term, key=voran, layer=orth, match=match:eq}}" +
+							"]}" +
+						"]" +
+					"}" +
+				"]}";
 		ct = new CosmasTree(query);
 		map = ct.getRequestMap().get("query").toString();
 		assertEquals(nhit1.replaceAll(" ", ""), map.replaceAll(" ", ""));
@@ -541,38 +547,50 @@
 		
 		query = "#BED(der Mann , +pe)";
 		String bed2 = 
-				"{@type=korap:group, operation=operation:position, frame=frame:endswith, operands=[" +
-					"{@type=korap:span, key=p}," +
-					"{@type=korap:group, operation=operation:sequence, operands=[" +
-						"{@type=korap:token, wrap={@type=korap:term, key=der, layer=orth, match=match:eq}}," +
-						"{@type=korap:token, wrap={@type=korap:term, key=Mann, layer=orth, match=match:eq}}" +
-					"]}" +
-				"]}";
+				"{@type=korap:group, operation=operation:submatch, classRef=[1], operands= [" +
+						"{@type=korap:group, operation=operation:position, frame=frame:endswith, operands=[" +
+							"{@type=korap:span, key=p}," +
+							"{@type=korap:group, operation=operation:class, class=1, operands=[" +
+								"{@type=korap:group, operation=operation:sequence, operands=[" +
+									"{@type=korap:token, wrap={@type=korap:term, key=der, layer=orth, match=match:eq}}," +
+									"{@type=korap:token, wrap={@type=korap:term, key=Mann, layer=orth, match=match:eq}}" +
+								"]}" +
+							"]}" +
+						"]}" +
+					"]}";
 		ct = new CosmasTree(query);
 		map = ct.getRequestMap().get("query").toString();
-//		assertEquals(bed2.replaceAll(" ", ""), map.replaceAll(" ", ""));
+		assertEquals(bed2.replaceAll(" ", ""), map.replaceAll(" ", ""));
 		
 		query = "#BED(der Mann , sa,-pa)";
 		String bed3 = 
-				"{@type=korap:group, operation=operation:and, operands=[" +
-					"{@type=korap:group, operation=operation:position, frame=frame:startswith, operands=[" +
-						"{@type=korap:span, key=s}," +
-						"{@type=korap:group, operation=operation:sequence, operands=[" +
-							"{@type=korap:token, wrap={@type=korap:term, key=der, layer=orth, match=match:eq}}," +
-							"{@type=korap:token, wrap={@type=korap:term, key=Mann, layer=orth, match=match:eq}}" +
-						"]}" +
-					"]}," +
-					"{@type=korap:group, operation=operation:position, frame=frame:startswith, exclude=true, operands=[" +
-						"{@type=korap:span, key=p}," +
-						"{@type=korap:group, operation=operation:sequence, operands=[" +
-							"{@type=korap:token, wrap={@type=korap:term, key=der, layer=orth, match=match:eq}}," +
-							"{@type=korap:token, wrap={@type=korap:term, key=Mann, layer=orth, match=match:eq}}" +
+				"{@type=korap:group, operation=operation:submatch, classRef=[1], operands=[" +
+					"{@type=korap:group, operation=operation:sequence, distances=[" +
+						"{@type=korap:distance, key=w, min=0, max=0}" +
+					"], operands=[" +
+						"{@type=korap:group, operation=operation:position, frame=frame:startswith, operands=[" +
+							"{@type=korap:span, key=s}," +
+							"{@type=korap:group, operation=operation:class, class=1, operands=[" +
+								"{@type=korap:group, operation=operation:sequence, operands=[" +
+									"{@type=korap:token, wrap={@type=korap:term, key=der, layer=orth, match=match:eq}}," +
+									"{@type=korap:token, wrap={@type=korap:term, key=Mann, layer=orth, match=match:eq}}" +
+								"]}" +
+							"]}" +
+						"]}," +
+						"{@type=korap:group, operation=operation:position, frame=frame:startswith, exclude=true, operands=[" +
+							"{@type=korap:span, key=p}," +
+							"{@type=korap:group, operation=operation:class, class=1, operands=[" +
+								"{@type=korap:group, operation=operation:sequence, operands=[" +
+									"{@type=korap:token, wrap={@type=korap:term, key=der, layer=orth, match=match:eq}}," +
+									"{@type=korap:token, wrap={@type=korap:term, key=Mann, layer=orth, match=match:eq}}" +
+								"]}" +
+							"]}" +
 						"]}" +
 					"]}" +
 				"]}";
 		ct = new CosmasTree(query);
 		map = ct.getRequestMap().get("query").toString();
-//		assertEquals(bed3.replaceAll(" ", ""), map.replaceAll(" ", ""));
+		assertEquals(bed3.replaceAll(" ", ""), map.replaceAll(" ", ""));
 	}
 	
 }