Implemented QueryContextRewrite (#755)

Change-Id: I14f62131063c114acdfa5cb3cb6f9eeff169d6cb
diff --git a/src/main/java/de/ids_mannheim/korap/config/KustvaktConfiguration.java b/src/main/java/de/ids_mannheim/korap/config/KustvaktConfiguration.java
index 1647e41..e6d2fca 100644
--- a/src/main/java/de/ids_mannheim/korap/config/KustvaktConfiguration.java
+++ b/src/main/java/de/ids_mannheim/korap/config/KustvaktConfiguration.java
@@ -47,7 +47,7 @@
 
     public final static Logger log = LoggerFactory
             .getLogger(KustvaktConfiguration.class);
-    
+
     private String vcInCaching;
 
     private String indexDir;
@@ -58,6 +58,9 @@
 
     private String serverHost;
 
+    private int maxTokenContext;
+    private int maxTokenMatch;
+
     private int maxhits;
     private int returnhits;
     private String keystoreLocation;
@@ -224,6 +227,9 @@
         // cache
         totalResultCacheEnabled = Boolean.valueOf(properties.getProperty(
                 "cache.total.results.enabled","true"));
+
+        maxTokenContext = Integer.parseInt(properties.getProperty(
+                "max.token.context.size", "0"));
     }
 
     @Deprecated
diff --git a/src/main/java/de/ids_mannheim/korap/rewrite/CollectionRewrite.java b/src/main/java/de/ids_mannheim/korap/rewrite/CollectionRewrite.java
index 0c3ee07..56b0092 100644
--- a/src/main/java/de/ids_mannheim/korap/rewrite/CollectionRewrite.java
+++ b/src/main/java/de/ids_mannheim/korap/rewrite/CollectionRewrite.java
@@ -150,7 +150,7 @@
 
         KoralCollectionQueryBuilder builder = new KoralCollectionQueryBuilder();
         RewriteIdentifier identifier = new KoralNode.RewriteIdentifier(
-                Attributes.AVAILABILITY, user.getCorpusAccess());
+                Attributes.AVAILABILITY, user.getCorpusAccess().name());
         JsonNode rewrittenNode;
 
         if (jsonNode.has("collection")) {
diff --git a/src/main/java/de/ids_mannheim/korap/rewrite/KoralNode.java b/src/main/java/de/ids_mannheim/korap/rewrite/KoralNode.java
index f05f864..0893820 100644
--- a/src/main/java/de/ids_mannheim/korap/rewrite/KoralNode.java
+++ b/src/main/java/de/ids_mannheim/korap/rewrite/KoralNode.java
@@ -92,22 +92,23 @@
             else if (value instanceof JsonNode)
                 n.put(name, (JsonNode) value);
 
-            if (ident != null)
-                name = ident.toString();
+//            if (ident != null)
+//                name = ident.toString();
 
-            this.rewrites.add("override", name);
+            this.rewrites.add("override", null, ident);
         }
     }
 
     public void replaceAt (String path, Object value, RewriteIdentifier ident) {
-        if (this.node.isObject() && !this.node.at(path).isMissingNode()) {
+        if (this.node.isObject() && 
+                !this.node.at(path).isMissingNode()) {
             ObjectNode n = (ObjectNode) this.node.at(path);
             n.removeAll();
             n.putAll((ObjectNode) value);
 
             String name = path;
             if (ident != null)
-                name = ident.toString();
+                name = ident.toString(); // scope is simply RewriteIdentifier ?? 
 
             this.rewrites.add("override", name);
         }
@@ -169,16 +170,31 @@
 
     public static class RewriteIdentifier {
 
-        private String key, value;
+        private String scope, value;
+        private Object source;
 
-        public RewriteIdentifier (String key, Object value) {
-            this.key = key;
-            this.value = value.toString();
+        public RewriteIdentifier (String scope, String value) {
+            this.scope = scope;
+            this.value = value;
         }
-
+        
+        public RewriteIdentifier (String scope, String value, Object source) {
+            this.scope = scope;
+            this.value = value;
+            this.source = source;
+        }
+        
+        public String getScope () {
+            return scope;
+        }
+        
+        public Object getSource () {
+            return source;
+        }
+        
         @Override
         public String toString () {
-            return key + "(" + value + ")";
+            return scope + "(" + value + ")";
         }
 
     }
@@ -204,6 +220,19 @@
             this.rewrites.add(rewrite);
             return this;
         }
+        
+        public KoralRewriteBuilder add (String op, String scope, RewriteIdentifier ri) {
+            KoralRewrite rewrite = new KoralRewrite();
+            rewrite.setOperation(op);
+            if (ri.getScope() != null) {
+                rewrite.setScope(ri.getScope());
+            }
+            if (ri.getSource() != null) {
+                rewrite.setSource(ri.getSource());
+            }
+            this.rewrites.add(rewrite);
+            return this;
+        }
 
         public JsonNode build (JsonNode node) {
             for (KoralRewrite rewrite : this.rewrites) {
@@ -234,24 +263,27 @@
 
     private static class KoralRewrite {
 
-        private Map<String, String> map;
+        private Map<String, Object> map;
 
         private KoralRewrite () {
             this.map = new LinkedHashMap<>();
             this.map.put("@type", "koral:rewrite");
             this.map.put("src", "Kustvakt");
+            this.map.put("origin", "Kustvakt");
         }
 
-        public KoralRewrite setOperation (String op) {
+        public void setOperation (String op) {
             if (!op.startsWith("operation:"))
                 op = "operation:" + op;
             this.map.put("operation", op);
-            return this;
         }
 
-        public KoralRewrite setScope (String scope) {
+        public void setScope (String scope) {
             this.map.put("scope", scope);
-            return this;
+        }
+        
+        public void setSource(Object source) {
+            this.map.put("source", source);
         }
 
     }
@@ -269,4 +301,11 @@
         return this.wrapNode(this.node.get(i));
     }
 
+    public int asInt() {
+        return this.node.asInt();
+    }
+    
+    public String asText(){
+        return this.node.asText();
+    }
 }
diff --git a/src/main/java/de/ids_mannheim/korap/rewrite/QueryContextRewrite.java b/src/main/java/de/ids_mannheim/korap/rewrite/QueryContextRewrite.java
new file mode 100644
index 0000000..1f75e21
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/rewrite/QueryContextRewrite.java
@@ -0,0 +1,55 @@
+package de.ids_mannheim.korap.rewrite;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+
+import de.ids_mannheim.korap.config.KustvaktConfiguration;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.rewrite.KoralNode.RewriteIdentifier;
+import de.ids_mannheim.korap.user.User;
+import de.ids_mannheim.korap.utils.JsonUtils;
+
+@Component
+public class QueryContextRewrite implements RewriteTask.RewriteQuery {
+
+    @Autowired
+    private KustvaktConfiguration config;
+
+    @Override
+    public KoralNode rewriteQuery (KoralNode node, KustvaktConfiguration config,
+            User user) throws KustvaktException {
+        
+        if (config.getMaxTokenContext() > 0) {
+            boolean isContextCut = false;
+            KoralNode context = node.at("/meta/context");
+            isContextCut = cutContext(context, "left");
+            isContextCut = cutContext(context, "right") || isContextCut;
+            if (isContextCut) context.buildRewrites();
+        }
+        return node;
+    }
+    
+    private boolean cutContext (KoralNode context, String position) 
+            throws KustvaktException {
+        KoralNode contextPosition = context.at("/" + position);
+        String type = contextPosition.at("/0").asText();
+
+        if (type.equals("token")) {
+            int length = contextPosition.at("/1").asInt();
+            int maxContextLength = config.getMaxTokenContext();
+            if (length > maxContextLength) {
+                JsonNode sourceNode = JsonUtils
+                        .readTree(contextPosition.toString());
+                ArrayNode arrayNode = (ArrayNode) contextPosition.rawNode();
+                arrayNode.set(1, maxContextLength);
+                context.replace(position, arrayNode, new RewriteIdentifier(
+                        position, null, sourceNode));
+                return true;
+            }
+        }
+        return false;
+    }
+}
\ No newline at end of file