meta query serialization for virtual collections (filter and extend)
diff --git a/pom.xml b/pom.xml
index 87d5e6f..27a2667 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,13 +6,13 @@
       <artifactId>KorAP-core-modules</artifactId>
       <version>1.0</version>
   </parent>
-
   
   <groupId>KorAP-modules</groupId>
   <artifactId>KorAP-querySerialization</artifactId>
   <version>0.0.1</version>
   <packaging>jar</packaging>
 
+
   <name>KorAP-querySerialization</name>
   <url>http://maven.apache.org</url>
 
@@ -22,12 +22,6 @@
 
   <dependencies>
     <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <version>3.8.1</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
     	<groupId>org.antlr</groupId>
     	<artifactId>antlr4-runtime</artifactId>
     	<version>4.0</version>
@@ -38,17 +32,17 @@
     	<version>2.2.2</version>
     </dependency>
     <dependency>
-    	<groupId>com.fasterxml.jackson.core</groupId>
-    	<artifactId>jackson-databind</artifactId>
-    	<version>2.2.2</version>
-    </dependency>
-    <dependency>
     	<groupId>KorAP-modules</groupId>
     	<artifactId>KorAP-PoliqarpParser</artifactId>
     	<version>0.05</version>
     </dependency>
+      <dependency>
+          <groupId>junit</groupId>
+          <artifactId>junit</artifactId>
+          <version>4.11</version>
+          <scope>test</scope>
+      </dependency>
   </dependencies>
-
   <build>
     <sourceDirectory>${basedir}/src/main/java</sourceDirectory>
     <outputDirectory>${basedir}/bin</outputDirectory>
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/MetaCollectionSerializer.java b/src/main/java/de/ids_mannheim/korap/query/serialize/MetaCollectionSerializer.java
new file mode 100644
index 0000000..f80aa83
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/MetaCollectionSerializer.java
@@ -0,0 +1,142 @@
+package de.ids_mannheim.korap.query.serialize;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author hanl
+ * @date 04/12/2013
+ */
+public class MetaCollectionSerializer {
+
+    public String meta1 = "{\n" +
+            "            \"@type\": \"korap:meta-filter\",\n" +
+            "            \"@id\": \"korap-filter#id-23\",\n" +
+            "            \"@value\": {\n" +
+            "                \"@type\": \"korap:term\",\n" +
+            "                \"@value\": \"wissenschaft\"\n" +
+            "            }\n" +
+            "        }\n";
+    public String meta2 = "{\n" +
+            "        \"@type\": \"korap:meta-filter\",\n" +
+            "        \"@id\": \"korap-filter#id-24\",\n" +
+            "        \"@value\": {\n" +
+            "            \"@type\": \"korap:group\",\n" +
+            "            \"relation\": \"and\",\n" +
+            "            \"operands\": [\n" +
+            "                {\n" +
+            "                    \"@type\": \"korap:term\",\n" +
+            "                    \"@field\": \"korap:field#pubPlace\",\n" +
+            "                    \"@value\": \"Erfurt\"\n" +
+            "                },\n" +
+            "                {\n" +
+            "                    \"@type\": \"korap:term\",\n" +
+            "                    \"@field\": \"korap:field#author\",\n" +
+            "                    \"@value\": \"Hesse\"\n" +
+            "                }\n" +
+            "            ]\n" +
+            "        }\n" +
+            "    }\n";
+    private MetaTypes types;
+    private ObjectMapper mapper;
+    private String meta3 = "{\n" +
+            "            \"@type\": \"korap:meta-extend\",\n" +
+            "            \"@id\": \"korap-filter#id-25\",\n" +
+            "            \"@value\": {\n" +
+            "                \"@type\": \"korap:group\",\n" +
+            "                \"relation\": \"and\",\n" +
+            "                \"operands\": [\n" +
+            "                    {\n" +
+            "                        \"@type\": \"korap:group\",\n" +
+            "                        \"relation\": \"comment: other values can be 'since','until' in combination with a simple korap:term\",\n" +
+            "                        \"relation\": \"between\",\n" +
+            "                        \"@field\": \"korap:field#pubDate\",\n" +
+            "                        \"operands\": [\n" +
+            "                            {\n" +
+            "                                \"@type\": \"korap:date\",\n" +
+            "                                \"@value\": \"comment: either long value or String representation '2013-04-29'\",\n" +
+            "                                \"@value\": \"2011\"\n" +
+            "                            },\n" +
+            "                            {\n" +
+            "                                \"@type\": \"korap:date\",\n" +
+            "                                \"@value\": \"2013\"\n" +
+            "                            }\n" +
+            "                        ]\n" +
+            "                    },\n" +
+            "                    {\n" +
+            "                        \"@type\": \"korap:term\",\n" +
+            "                        \"@field\": \"korap:field#textClass\",\n" +
+            "                        \"@value\": \"freizeit\"\n" +
+            "                    }\n" +
+            "                ]\n" +
+            "            }\n" +
+            "        }";
+    private Map<String, Map> tester;
+
+    public MetaCollectionSerializer() {
+        this.types = new MetaTypes();
+        this.mapper = new ObjectMapper();
+        this.tester = tester();
+    }
+
+    //resources must be ordered: 0 without parent, 1 has 0 as parent, etc.
+    // what about extend?! is that also part of the VC meta query?!
+    public String serialize(String resource) throws IOException {
+        Map metas = new HashMap();
+        Map<String, String> pa = getParents(resource);
+        List<Map> parids = new ArrayList<>();
+        for (String key : pa.keySet()) {
+            Map re = types.mapify(pa.get(key));
+            parids.add(re);
+        }
+        metas.put("meta", parids);
+        return mapper.writeValueAsString(metas);
+    }
+
+    private Map<String, String> getParents(String id) {
+        Map<String, String> cursor = getResource(id);
+        Map<String, String> parents = new HashMap<>();
+
+        if (cursor.get("parent") != null && !cursor.get("parent").isEmpty()) {
+            parents.put(id, cursor.get("query"));
+            parents.putAll(getParents(cursor.get("parent")));
+        } else
+            parents.put(id, cursor.get("query"));
+        return parents;
+
+    }
+
+    //todo: connection to database module!
+    public Map<String, String> getResource(String id) {
+        return tester.get(id);
+
+    }
+
+    private Map<String, Map> tester() {
+        Map<String, Map> l = new HashMap<>();
+        Map<String, String> s = new HashMap<>();
+        s.put("id", "23");
+        s.put("parent", "");
+        s.put("query", meta1);
+
+        Map<String, String> s2 = new HashMap<>();
+        s2.put("id", "24");
+        s2.put("parent", "23");
+        s2.put("query", meta2);
+
+        Map<String, String> s3 = new HashMap<>();
+        s3.put("id", "25");
+        s3.put("parent", "24");
+        s3.put("query", meta3);
+        l.put("23", s);
+        l.put("24", s2);
+        l.put("25", s3);
+        return l;
+    }
+
+}
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/MetaQuerySerializer.java b/src/main/java/de/ids_mannheim/korap/query/serialize/MetaQuerySerializer.java
new file mode 100644
index 0000000..6db54f4
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/MetaQuerySerializer.java
@@ -0,0 +1,106 @@
+package de.ids_mannheim.korap.query.serialize;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * serializes a map of meta queries to JSON-LD. Currently this only works for simple mode queries (simple AND relation, except for date ranges)
+ * Expert mode requires a full blown parser (since different combinations of OR and AND relations are possible)
+ * also normalizes dates to year-month-day
+ * <p/>
+ * <p/>
+ * User: hanl
+ * Date: 11/14/13
+ * Time: 2:03 PM
+ */
+public class MetaQuerySerializer {
+
+    private ObjectMapper mapper;
+    private MetaTypes types;
+
+    public MetaQuerySerializer() {
+        this.mapper = new ObjectMapper();
+        this.types = new MetaTypes();
+    }
+
+    // construct pubdate range query as "pubDate:'<date>' ~ pubDate:'<date>'"
+    //todo: how to handle regex types?
+    // only handles AND relation between query attributes and values!
+    // value pair : pubdate=<date>, pubPlace=<place>, etc.
+    public List serializeQueries(Map<String, String> queries) {
+        boolean single = true;
+        boolean multypes = queries.keySet().size() > 1;
+        List metavalue;
+        String def_key = null;
+        if (queries.size() > 1)
+            single = false;
+
+        List value = new ArrayList<>();
+        for (String key : queries.keySet()) {
+            if (!multypes)
+                def_key = key;
+            String[] dr;
+            if (queries.get(key).contains("~")) {
+                dr = queries.get(key).split("~");
+                Map fd = types.createTerm(null, null, dr[0].trim(), "korap:date");
+                Map td = types.createTerm(null, null, dr[1].trim(), "korap:date");
+                Map dg = types.createGroup("between", key, Arrays.asList(fd, td));
+                value.add(dg);
+                continue;
+            } else if (queries.get(key).contains(">")) {
+                dr = queries.get(key).split(">");
+                Map fd = types.createTerm(null, null, dr[0].trim(), "korap:date");
+                Map td = types.createTerm(null, null, dr[1].trim(), "korap:date");
+                Map dg = types.createGroup("between", key, Arrays.asList(fd, td));
+                value.add(dg);
+                continue;
+            } else if (queries.get(key).contains("<")) {
+                dr = queries.get(key).split("<");
+                Map fd = types.createTerm(null, null, dr[0].trim(), "korap:date");
+                Map td = types.createTerm(null, null, dr[1].trim(), "korap:date");
+                Map dg = types.createGroup("between", key, Arrays.asList(fd, td));
+                value.add(dg);
+                continue;
+            }
+
+            Map term;
+            if (multypes)
+                term = types.createTerm(key, null, queries.get(key).trim(), null);
+            else
+                term = types.createTerm(null, null, queries.get(key).trim(), null);
+            value.add(term);
+        }
+
+        // todo: missing: - takes only one resource, but resources can be chained!
+        // only filters, no extension
+//        metavalue.put("meta", Arrays.asList(types.createMetaFilter(resource, (Map) value.get(0))));
+        if (single)
+            metavalue = Arrays.asList(types.createMetaFilter((Map) value.get(0)));
+        else {
+            Map group;
+            if (!multypes)
+                group = types.createGroup("and", def_key, value);
+            else
+                group = types.createGroup("and", null, value);
+//            metavalue.put("meta", Arrays.asList(types.createMetaFilter(resource, group)));
+            metavalue = Arrays.asList(types.createMetaFilter(group));
+        }
+        return metavalue;
+    }
+
+    public String stringify(Map<String, String> queries) throws IOException {
+        Map f = new HashMap();
+        f.put("meta", serializeQueries(queries));
+        return mapper.writeValueAsString(f);
+    }
+
+    public JsonNode jsonify(Map<String, String> queries) {
+        List s = serializeQueries(queries);
+        return mapper.valueToTree(s);
+    }
+
+
+}
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/MetaSerializer.java b/src/main/java/de/ids_mannheim/korap/query/serialize/MetaSerializer.java
deleted file mode 100644
index 12901f5..0000000
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/MetaSerializer.java
+++ /dev/null
@@ -1,127 +0,0 @@
-package de.ids_mannheim.korap.query.serialize;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-import java.io.IOException;
-import java.util.*;
-
-/**
- *
- * serializes a map of meta queries to JSON-LD. Currently this only works for simple mode queries (simple AND relation, except for date ranges)
- * Expert mode requires a full blown parser (since different combinations of OR and AND relations are possible)
- * also normalizes dates to year-month-day
- *
- *
- * User: hanl
- * Date: 11/14/13
- * Time: 2:03 PM
- */
-public class MetaSerializer {
-
-    private ObjectMapper mapper;
-
-    public MetaSerializer() {
-        this.mapper = new ObjectMapper();
-    }
-
-    private Map createGroup(String relation, String field, List terms) {
-        if (relation == null)
-            return null;
-
-        Map kgroup = new LinkedHashMap<>();
-        kgroup.put("@type", "korap:group");
-        if (field != null)
-            kgroup.put("field", "korap:field#" + field);
-        kgroup.put("relation", relation);
-        kgroup.put("operands", terms);
-        return kgroup;
-    }
-
-
-    private Map createTerm(String field, String subtype, String value, String type) {
-        Map term = new LinkedHashMap<>();
-        if (type == null)
-            type = "korap:term";
-        term.put("@type", type);
-        if (field != null)
-            term.put("@field", "korap:field#" + field);
-        if (subtype != null)
-            term.put("subtype", "korap:value#" + subtype);
-        term.put("@value", value);
-        return term;
-    }
-
-    private Map createMeta(String resource, Map value) {
-        Map meta = new LinkedHashMap();
-        meta.put("@type", "korap:meta-filter");
-        meta.put("@id", "korap-filter#" + resource);
-        meta.put("@value", value);
-        return meta;
-    }
-
-    private Map createMetaFilter(String resource, Map value) {
-        return null;
-    }
-
-
-    // construct pubdate range query as "pubDate:'<date>' ~ pubDate:'<date>'"
-    //todo: how to handle regex types?
-    // only handles AND relation between query attributes!
-    // value pair : pubdate=<date>, pubPlace=<place>, etc.
-    private Map serialize(String resource, Map<String, String> queries) {
-        boolean single = true;
-        boolean multypes = new HashSet<>(queries.keySet()).size() > 1;
-        Map metavalue = new LinkedHashMap<>();
-        String def_key = null;
-        if (queries.size() > 1)
-            single = false;
-
-        List value = new ArrayList<>();
-        for (String key : queries.keySet()) {
-            if (!multypes)
-                def_key = key;
-            if (queries.get(key).contains("~")) {
-                String[] dr = queries.get(key).split("~");
-                Map fd = createTerm(null, null, dr[0].trim(), "korap:date");
-                Map td = createTerm(null, null, dr[1].trim(), "korap:date");
-                Map dg = createGroup("between", key, Arrays.asList(fd, td));
-                value.add(dg);
-                continue;
-            }
-
-            Map term;
-            if (multypes)
-                term = createTerm(key, null, queries.get(key).trim(), null);
-            else
-                term = createTerm(null, null, queries.get(key).trim(), null);
-            value.add(term);
-        }
-
-        if (single)
-            metavalue.put("meta", Arrays.asList(createMeta(resource, (Map) value.get(0))));
-        else {
-            Map group;
-            if (!multypes)
-                group = createGroup("and", def_key, value);
-            else
-                group = createGroup("and", null, value);
-            metavalue.put("meta", Arrays.asList(createMeta(resource, group)));
-        }
-        return metavalue;
-    }
-
-    private String formatDate(String date) {
-        return "";
-    }
-
-
-    public String stringify(String resource, Map<String, String> queries) throws IOException {
-        Map s = serialize(resource, queries);
-        return mapper.writeValueAsString(s);
-    }
-
-
-
-
-
-}
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/MetaTypes.java b/src/main/java/de/ids_mannheim/korap/query/serialize/MetaTypes.java
new file mode 100644
index 0000000..887f176
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/MetaTypes.java
@@ -0,0 +1,95 @@
+package de.ids_mannheim.korap.query.serialize;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import java.io.IOException;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author hanl
+ * @date 04/12/2013
+ */
+public class MetaTypes {
+
+    private ObjectMapper mapper;
+
+    public MetaTypes() {
+        this.mapper = new ObjectMapper();
+    }
+
+    public Map createGroup(String relation, String field, List terms) {
+        if (relation == null)
+            return null;
+
+        Map kgroup = new LinkedHashMap<>();
+        kgroup.put("@type", "korap:group");
+        if (field != null)
+            kgroup.put("field", "korap:field#" + field);
+        kgroup.put("relation", relation);
+        kgroup.put("operands", terms);
+        return kgroup;
+    }
+
+    public Map createTerm(String field, String subtype, String value, String type) {
+        Map term = new LinkedHashMap<>();
+        if (type == null)
+            type = "korap:term";
+        term.put("@type", type);
+        if (field != null)
+            term.put("@field", "korap:field#" + field);
+        if (subtype != null)
+            term.put("subtype", "korap:value#" + subtype);
+        term.put("@value", value);
+        return term;
+    }
+
+    public Map createResourceFilter(String resource, Map value) {
+        Map meta = new LinkedHashMap();
+        meta.put("@type", "korap:meta-filter");
+        meta.put("@id", "korap-filter#" + resource);
+        meta.put("@value", value);
+        return meta;
+    }
+
+    public Map createResourceFilter(String resource, String value) throws IOException {
+        return createResourceFilter(resource, mapify(value));
+    }
+
+    public Map createResourceExtend(String resource, Map value) {
+        Map meta = new LinkedHashMap();
+        meta.put("@type", "korap:meta-extend");
+        meta.put("@id", "korap-filter#" + resource);
+        meta.put("@value", value);
+        return meta;
+    }
+
+    public Map createMetaFilter(Map value) {
+        Map meta = new LinkedHashMap();
+        meta.put("@type", "korap:meta-filter");
+        meta.put("@value", value);
+        return meta;
+    }
+
+    public Map createMetaExtend(Map value) {
+        Map meta = new LinkedHashMap();
+        meta.put("@type", "korap:meta-extend");
+        meta.put("@value", value);
+        return meta;
+    }
+
+    public String formatDate(String date) {
+        return "";
+    }
+
+    public Map mapify(String s) throws IOException {
+        return mapper.readValue(s, Map.class);
+    }
+
+    public String stringify(Map m) throws JsonProcessingException {
+        return mapper.writeValueAsString(m);
+    }
+
+}
diff --git a/src/test/java/MetaQuerySerializationTest.java b/src/test/java/MetaQuerySerializationTest.java
new file mode 100644
index 0000000..71ca546
--- /dev/null
+++ b/src/test/java/MetaQuerySerializationTest.java
@@ -0,0 +1,51 @@
+import de.ids_mannheim.korap.query.serialize.MetaCollectionSerializer;
+import de.ids_mannheim.korap.query.serialize.MetaQuerySerializer;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author hanl
+ * @date 04/12/2013
+ */
+
+@RunWith(JUnit4.class)
+public class MetaQuerySerializationTest {
+
+    private MetaQuerySerializer serializer;
+
+    public MetaQuerySerializationTest() {
+        serializer = new MetaQuerySerializer();
+    }
+
+    @Test
+    public void test() throws IOException {
+        Map<String, String> j = new HashMap();
+        j.put("author", "Goethe");
+        j.put("pubPLace", "Erfurt");
+        j.put("textClass", "wissenschaft");
+        String s = serializer.stringify(j);
+//        System.out.println("value reference " + s);
+    }
+
+    @Test
+    public void testSingle() throws IOException {
+        Map<String, String> j = new HashMap();
+        j.put("textClass", "wissenschaft");
+        String s = serializer.stringify(j);
+//        System.out.println("value reference test single " + s);
+    }
+
+    @Test
+    public void testResourceMeta() throws IOException {
+        MetaCollectionSerializer ser = new MetaCollectionSerializer();
+        String s = ser.serialize("25");
+        System.out.println(" --- RESULT JSON " + s);
+
+
+    }
+}