- highlighted classes explicit in meta
- PQ+: 'dependency(X,Y)' as shortcut for 'relatesTo(d:X,Y)'

diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/AbstractQueryProcessor.java b/src/main/java/de/ids_mannheim/korap/query/serialize/AbstractQueryProcessor.java
index ca09dc7..501c190 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/AbstractQueryProcessor.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/AbstractQueryProcessor.java
@@ -11,85 +11,91 @@
 import org.slf4j.Logger;
 
 public abstract class AbstractQueryProcessor {
-	
-	Logger log;
-	/**
-	 *  The query
-	 */
-	String query;
-	/**
-	 * Top-level map representing the whole request.
-	 */
-	LinkedHashMap<String, Object> requestMap = new LinkedHashMap<String, Object>();
-	/**
-	 * Keeps track of open node categories
-	 */
-	LinkedList<String> openNodeCats = new LinkedList<String>();
-	/**
-	 * Keeps track of all visited nodes in a tree
-	 */
-	List<ParseTree> visited = new ArrayList<ParseTree>();
-	/**
-	 * Keeps track of active object.
-	 */
-	LinkedList<LinkedHashMap<String, Object>> objectStack = new LinkedList<LinkedHashMap<String, Object>>();
-	/**
-	 * Keeps track of how many objects there are to pop after every recursion of {@link #processNode(ParseTree)}
-	 */
-	LinkedList<Integer> objectsToPop = new LinkedList<Integer>();
-	/**
-	 * If true, print debug statements
-	 */
-	public static boolean verbose = false;
-	ParseTree currentNode = null;
-	Integer stackedObjects = 0;
-	private ArrayList<List<Object>> errors = new ArrayList<List<Object>>();
-	private ArrayList<List<Object>> warnings = new ArrayList<List<Object>>();
-	private ArrayList<List<Object>> messages = new ArrayList<List<Object>>();
-	LinkedHashMap<String, Object> collection = new LinkedHashMap<String,Object>();
-	
-	AbstractQueryProcessor() {
-		requestMap.put("@context", "http://ids-mannheim.de/ns/KorAP/json-ld/v0.2/context.jsonld");
-		requestMap.put("errors", errors);
-		requestMap.put("warnings", warnings);
-		requestMap.put("messages", messages);
-		requestMap.put("collection", collection);
-		requestMap.put("query", new LinkedHashMap<String, Object>());
-		requestMap.put("meta", new LinkedHashMap<String, Object>());
-	}
-	
-	public abstract void process(String query);
-	
-	public void addWarning(int code, String msg) {
-		List<Object> warning = Arrays.asList(new Object[]{code, msg}); 
-		warnings.add(warning);
-	}
-	
-	public void addWarning(String msg) {
-		List<Object> warning = Arrays.asList(new Object[]{msg}); 
-		warnings.add(warning);
-	}
-	
-	public void addMessage(int code, String msg) {
-		List<Object> message = Arrays.asList(new Object[]{code, msg}); 
-		messages.add(message);
-	}
-	
-	public void addMessage(String msg) {
-		List<Object> message = Arrays.asList(new Object[]{msg}); 
-		messages.add(message);
-	}
-	
-	public void addError(int code, String msg) {
-		List<Object> error = Arrays.asList(new Object[]{code, msg}); 
-		errors.add(error);
-	}
 
-	public void addError(List<Object> fullErrorMsg) {
-		errors.add(fullErrorMsg);
-	}
-	
-	public Map<String, Object> getRequestMap() {
-		return requestMap;
-	}
+    Logger log;
+    /**
+     *  The query
+     */
+    String query;
+    /**
+     * Top-level map representing the whole request.
+     */
+    LinkedHashMap<String, Object> requestMap = new LinkedHashMap<String, Object>();
+    /**
+     * Keeps track of open node categories
+     */
+    LinkedList<String> openNodeCats = new LinkedList<String>();
+    /**
+     * Keeps track of all visited nodes in a tree
+     */
+    List<ParseTree> visited = new ArrayList<ParseTree>();
+    /**
+     * Keeps track of active object.
+     */
+    LinkedList<LinkedHashMap<String, Object>> objectStack = new LinkedList<LinkedHashMap<String, Object>>();
+    /**
+     * Keeps track of how many objects there are to pop after every recursion of {@link #processNode(ParseTree)}
+     */
+    LinkedList<Integer> objectsToPop = new LinkedList<Integer>();
+    /**
+     * If true, print debug statements
+     */
+    public static boolean verbose = false;
+    protected Integer stackedObjects = 0;
+    private ArrayList<List<Object>> errors = new ArrayList<List<Object>>();
+    private ArrayList<List<Object>> warnings = new ArrayList<List<Object>>();
+    private ArrayList<List<Object>> messages = new ArrayList<List<Object>>();
+    private LinkedHashMap<String, Object> collection = new LinkedHashMap<String,Object>();
+    private LinkedHashMap<String, Object> meta = new LinkedHashMap<String,Object>();
+    private ArrayList<Integer> highlightClasses = new ArrayList<Integer>();
+
+    AbstractQueryProcessor() {
+        requestMap.put("@context", "http://ids-mannheim.de/ns/KorAP/json-ld/v0.2/context.jsonld");
+        requestMap.put("errors", errors);
+        requestMap.put("warnings", warnings);
+        requestMap.put("messages", messages);
+        requestMap.put("collection", collection);
+        requestMap.put("query", new LinkedHashMap<String, Object>());
+        requestMap.put("meta", meta);
+    }
+
+    public abstract void process(String query);
+
+    public void addWarning(int code, String msg) {
+        List<Object> warning = Arrays.asList(new Object[]{code, msg}); 
+        warnings.add(warning);
+    }
+
+    public void addWarning(String msg) {
+        List<Object> warning = Arrays.asList(new Object[]{msg}); 
+        warnings.add(warning);
+    }
+
+    public void addMessage(int code, String msg) {
+        List<Object> message = Arrays.asList(new Object[]{code, msg}); 
+        messages.add(message);
+    }
+
+    public void addMessage(String msg) {
+        List<Object> message = Arrays.asList(new Object[]{msg}); 
+        messages.add(message);
+    }
+
+    public void addError(int code, String msg) {
+        List<Object> error = Arrays.asList(new Object[]{code, msg}); 
+        errors.add(error);
+    }
+
+    public void addError(List<Object> fullErrorMsg) {
+        errors.add(fullErrorMsg);
+    }
+
+    public void addHighlightClass(int classId) {
+        highlightClasses.add(classId);
+        meta.put("highlight", highlightClasses);
+    }
+
+    public Map<String, Object> getRequestMap() {
+        return requestMap;
+    }
 }
\ No newline at end of file
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/AnnisQueryProcessor.java b/src/main/java/de/ids_mannheim/korap/query/serialize/AnnisQueryProcessor.java
index 2bb45ad..37a32b3 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/AnnisQueryProcessor.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/AnnisQueryProcessor.java
@@ -65,7 +65,7 @@
     /**
      * Keeps track of operation:class numbers.
      */
-    int classCounter = 0;
+    int classCounter = 1;
     /**
      * Keeps track of numers of relations processed (important when dealing with multiple predications).
      */
@@ -285,13 +285,13 @@
             }
         }
     }
-
-    private void processUnary_linguistic_term(ParseTree node) {
-        LinkedHashMap<String, Object> unaryOperator = parseUnaryOperator(node);
-        String reference = node.getChild(0).toStringTree(parser).substring(1);
-        LinkedHashMap<String, Object> object = nodeVariables.get(reference);
-        object.putAll(unaryOperator);
-    }
+//
+//    private void processUnary_linguistic_term(ParseTree node) {
+//        LinkedHashMap<String, Object> unaryOperator = parseUnaryOperator(node);
+//        String reference = node.getChild(0).toStringTree(parser).substring(1);
+//        LinkedHashMap<String, Object> object = nodeVariables.get(reference);
+//        object.putAll(unaryOperator);
+//    }
 
     private void processExprTop(ParseTree node) {
         List<ParseTree> andTopExprs = getChildrenWithCat(node, "andTopExpr");
@@ -398,7 +398,7 @@
                     try {
                         operand = KoralObjectGenerator.wrapInReference(operandStack.pop(), refClassMapping.get(ref), true);
                     } catch (NoSuchElementException e) {
-                        operand = KoralObjectGenerator.makeReference(refClassMapping.get(ref), true);
+                        operand = KoralObjectGenerator.makeReference(refClassMapping.get(ref));
                     }
                 }
                 nodeReferencesProcessed.put(ref, nodeReferencesProcessed.get(ref)+1);
@@ -550,7 +550,7 @@
                     LinkedHashMap<String,Object> positionGroup = KoralObjectGenerator.makePosition(new String[]{frame}, null);
                     operand2 = KoralObjectGenerator.wrapInClass(operand2, ++classCounter);
                     ((ArrayList<Object>) positionGroup.get("operands")).add(group);
-                    ((ArrayList<Object>) positionGroup.get("operands")).add(KoralObjectGenerator.makeReference(classCounter,true));
+                    ((ArrayList<Object>) positionGroup.get("operands")).add(KoralObjectGenerator.makeReference(classCounter));
                     group = positionGroup;
                 }
 
@@ -719,6 +719,22 @@
             //			relation.put("sharedClasses", sharedClasses);
             relation = KoralObjectGenerator.makePosition(frames, new String[]{});
             relation.put("groupType", "position");
+        } 
+        else if (operator.equals("near")) {
+            relation = new LinkedHashMap<String, Object>();
+            relation.put("groupType", "sequence");
+            ParseTree rangeSpec = getFirstChildWithCat(operatorNode, "rangeSpec");
+            ParseTree star = getFirstChildWithCat(operatorNode, "*");
+            ArrayList<Object> distances = new ArrayList<Object>();
+            if (star != null) {
+                distances.add(KoralObjectGenerator.makeDistance("w", 0, null));
+                relation.put("distances", distances);
+            }
+            if (rangeSpec != null) {
+                distances.add(parseDistance(rangeSpec));
+                relation.put("distances", distances);
+            }
+            relation.put("inOrder", false);
         }
         else if (operator.equals("identity")) {
             //TODO since ANNIS v. 3.1.6
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/Cosmas2QueryProcessor.java b/src/main/java/de/ids_mannheim/korap/query/serialize/Cosmas2QueryProcessor.java
index cabf32c..d0490b0 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/Cosmas2QueryProcessor.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/Cosmas2QueryProcessor.java
@@ -352,7 +352,7 @@
                 "TPEND");
 
         LinkedHashMap<String, Object> submatchgroup = 
-                KoralObjectGenerator.makeReference(128 + classCounter);
+                KoralObjectGenerator.makeReference(classCounter);
         ArrayList<Object> submatchOperands = new ArrayList<Object>();
         submatchgroup.put("operands", submatchOperands);
         putIntoSuperObject(submatchgroup);
@@ -398,7 +398,7 @@
                 // constraint applies
                 if (conditionCount > 1) {
                     LinkedHashMap<String, Object> focus = 
-                            KoralObjectGenerator.makeReference(128 + classCounter - 2);
+                            KoralObjectGenerator.makeReference(classCounter - 2);
                     ArrayList<Object> focusOperands = new ArrayList<Object>();
                     focus.put("operands", focusOperands);
                     focusOperands.add(matchesGroup);
@@ -416,15 +416,15 @@
     }
 
     private void processOPNHIT(Tree node) {
-        Integer[] classRef = new Integer[] { 128 + classCounter + 1,
-                128 + classCounter + 2 };
+        Integer[] classRef = new Integer[] { classCounter + 1,
+                classCounter + 2 };
         // classRef.add(classCounter + 1); // yes, do this twice (two
         // classes)!
         LinkedHashMap<String, Object> group = 
-                KoralObjectGenerator.makeReference(128 + classCounter);
+                KoralObjectGenerator.makeReference(classCounter);
         LinkedHashMap<String, Object> classRefCheck = 
                 KoralObjectGenerator.makeClassRefOp("classRefOp:inversion", classRef,
-                        classCounter + 128);
+                        classCounter);
         ArrayList<Object> operands = new ArrayList<Object>();
         operands.add(classRefCheck);
         group.put("operands", operands);
@@ -485,20 +485,20 @@
         ArrayList<String> check = 
                 (ArrayList<String>) positionOptions.get("classRefCheck");
         Integer[] classIn = 
-                new Integer[] { 128 + classCounter - 2, 128 + classCounter - 1 };
+                new Integer[] { classCounter - 2, classCounter - 1 };
         LinkedHashMap<String, Object> classRefCheck = 
                 KoralObjectGenerator.makeClassRefCheck(check, classIn,
-                        128 + classCounter);
+                        classCounter);
         ((ArrayList<Object>) classRefCheck.get("operands")).add(posgroup);
         LinkedHashMap<String, Object> focusGroup = null;
         if ((boolean) positionOptions.get("matchall") == true) {
             focusGroup = KoralObjectGenerator.makeClassRefOp("classRefOp:delete", 
-                    new Integer[]{128+classCounter++}, 128+classCounter);
+                    new Integer[]{classCounter++}, classCounter);
             ((ArrayList<Object>) focusGroup.get("operands")).add(classRefCheck);
         }
         else { // match only first argument
             focusGroup = KoralObjectGenerator.wrapInReference(classRefCheck,
-                    128 + classCounter);
+                    classCounter);
         }
         // wrap in 'merge' operation if grouping option is set
         if (positionOptions.containsKey("grouping")) {
@@ -596,7 +596,7 @@
             wrapOperandInClass(node, 1, classCounter);
             wrapOperandInClass(node, 2, classCounter);
             group = KoralObjectGenerator.wrapInReference(group,
-                    128 + classCounter++);
+                    classCounter++);
         }
         else if (openNodeCats.get(1).equals("OPNHIT")) {
             LinkedHashMap<String, Object> repetition = KoralObjectGenerator
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusQueryProcessor.java b/src/main/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusQueryProcessor.java
index 00da8d2..4a61c26 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusQueryProcessor.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusQueryProcessor.java
@@ -23,7 +23,7 @@
 
     private static Logger log = LoggerFactory
             .getLogger(PoliqarpPlusQueryProcessor.class);
-    private int classCounter = 128;
+    private int classCounter = 1;
 
     /**
      * Most centrally, this class maintains a set of nested maps and
@@ -83,8 +83,6 @@
         else
             visited.add(node);
 
-        currentNode = node;
-
         String nodeCat = getNodeCat(node);
         openNodeCats.push(nodeCat);
 
@@ -261,7 +259,8 @@
                     .toStringTree(parser));
         }
         LinkedHashMap<String, Object> classGroup = 
-                KoralObjectGenerator.makeSpanClass(classId, false);
+                KoralObjectGenerator.makeSpanClass(classId);
+        addHighlightClass(classId);
         putIntoSuperObject(classGroup);
         objectStack.push(classGroup);
         stackedObjects++;
@@ -321,7 +320,7 @@
     @SuppressWarnings("unchecked")
     private void processAlignment(ParseTree node) {
         LinkedHashMap<String, Object> alignClass = 
-                KoralObjectGenerator.makeSpanClass(++classCounter, false);
+                KoralObjectGenerator.makeSpanClass(classCounter);
         LinkedHashMap<String, Object> metaMap = 
                 (LinkedHashMap<String, Object>) requestMap.get("meta");
         if (metaMap.containsKey("alignment")) {
@@ -338,7 +337,7 @@
         else {
             metaMap.put("alignment", classCounter);
         }
-
+        classCounter++;
         putIntoSuperObject(alignClass);
         objectStack.push(alignClass);
         stackedObjects++;
@@ -413,6 +412,8 @@
         relation.put("wrap", term);
         if (node.getChild(0).getText().equals("dominates")) {
             term.put("layer", "c");
+        } else if (node.getChild(0).getText().equals("dependency")) {
+            term.put("layer", "d");
         }
         ParseTree relSpec = getFirstChildWithCat(node, "relSpec");
         ParseTree repetition = getFirstChildWithCat(node, "repetition");
@@ -452,15 +453,16 @@
                 addError(StatusCodes.UNDEFINED_CLASS_REFERENCE, msg);
             }
             // only allow class id up to 127
-            if (classId > 127) {
-                addWarning("Only class IDs up to 127 are allowed. Your class "
-                        + classId + " has been set back to 127. "
+            if (classId > 128) {
+                addWarning("Only class IDs up to 128 are allowed. Your class "
+                        + classId + " has been set back to 128. "
                         + "Check for possible conflict with other classes.");
-                classId = 127;
+                classId = 128;
             }
         }
         LinkedHashMap<String, Object> classGroup = 
-                KoralObjectGenerator.makeSpanClass(classId, false);
+                KoralObjectGenerator.makeSpanClass(classId);
+        addHighlightClass(classId);
         putIntoSuperObject(classGroup);
         objectStack.push(classGroup);
         stackedObjects++;
@@ -481,14 +483,14 @@
                 else {
                     try {
                         int classRef = Integer.parseInt(ref);
-                        // only allow class id up to 127
-                        if (classRef > 127) {
-                            addWarning("Only class references up to 127 are "
+                        // only allow class id up to 128
+                        if (classRef > 128) {
+                            addWarning("Only class references up to 128 are "
                                     + "allowed. Your reference to class "
-                                    + classRef + " has been set back to 127. "
+                                    + classRef + " has been set back to 128. "
                                     + "Check for possible conflict with "
                                     + "other classes.");
-                            classRef = 127;
+                            classRef = 128;
                         }
                         classRefs.add(classRef);
                     }
@@ -677,6 +679,8 @@
      *            negated, e.g. through a negation operator preceding
      *            the related token like "![base=foo]". Global
      *            negation affects the term's "match" parameter.
+     * @param mode 'token' or 'span' (tokens and spans are treated 
+     *            differently).
      * @return A term or termGroup object, depending on input
      */
     @SuppressWarnings("unchecked")
@@ -706,12 +710,17 @@
             // process layer: map "base" -> "lemma"
             if (layerNode != null) {
                 String layer = layerNode.getText();
-                if (layer.equals("base"))
-                    layer = "lemma";
-                if (mode.equals("span"))
+                if (mode.equals("span")) {
                     term.put("key", layer);
-                else
+                } else if (mode.equals("token")) {
+                    if (layer.equals("base")) {
+                        layer = "lemma"; }
+                    else if (layer.equals("punct")) {
+                        layer = "orth";
+                        term.put("type", "type:punct");
+                    }   
                     term.put("layer", layer);
+                }
             }
             // process key: 'normal' or regex?
             key = keyNode.getText();
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/util/KoralObjectGenerator.java b/src/main/java/de/ids_mannheim/korap/query/serialize/util/KoralObjectGenerator.java
index 804b8f9..befa081 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/util/KoralObjectGenerator.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/util/KoralObjectGenerator.java
@@ -99,9 +99,10 @@
     }
 
     public static LinkedHashMap<String, Object> makeSpanClass(int classCount) {
-        return makeSpanClass(classCount, true);
+        return makeSpanClass(classCount, false);
     }
 
+    @Deprecated
     public static LinkedHashMap<String, Object> makeSpanClass(int classId,
             boolean setBySystem) {
         LinkedHashMap<String, Object> group = new LinkedHashMap<String, Object>();
@@ -215,6 +216,7 @@
         return makeReference(classRefs, "focus");
     }
 
+    @Deprecated
     public static LinkedHashMap<String, Object> makeReference(int classRef,
             String operation, boolean setBySystem) {
         ArrayList<Integer> classRefs = new ArrayList<Integer>();
@@ -224,6 +226,7 @@
         return makeReference(classRefs, operation);
     }
 
+    @Deprecated
     public static LinkedHashMap<String, Object> makeReference(int classRef,
             boolean setBySystem) {
         ArrayList<Integer> classRefs = new ArrayList<Integer>();
@@ -270,7 +273,7 @@
     public static LinkedHashMap<String, Object> wrapInReference(
             LinkedHashMap<String, Object> group, Integer classId, 
             boolean setBySystem) {
-        LinkedHashMap<String, Object> refGroup = makeReference(classId, setBySystem);
+        LinkedHashMap<String, Object> refGroup = makeReference(classId);
         ArrayList<Object> operands = new ArrayList<Object>();
         operands.add(group);
         refGroup.put("operands", operands);
@@ -280,7 +283,7 @@
     @SuppressWarnings("unchecked")
     public static LinkedHashMap<String, Object> wrapInClass(
             LinkedHashMap<String, Object> group, Integer classId) {
-        LinkedHashMap<String, Object> classGroup = makeSpanClass(classId, true);
+        LinkedHashMap<String, Object> classGroup = makeSpanClass(classId);
         ((ArrayList<Object>) classGroup.get("operands")).add(group);
         return classGroup;
     }