meta serialization bug fixes;
convenience meta query builder class MetaQuery to provide better access to json serialization.
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/JsonGenerator.java b/src/main/java/de/ids_mannheim/korap/query/serialize/JsonGenerator.java
index a582540..243a4d7 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/JsonGenerator.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/JsonGenerator.java
@@ -126,10 +126,7 @@
         }
         Map<String, Object> requestMap = ast.getRequestMap();
         try {
-            List meta_re = serializer.serializeResources(parents);
-
-//            JsonNode node = mapper.valueToTree(parents);
-//            JsonNode arr = node.get("meta");
+            List<Map> meta_re = serializer.serializeResources(parents);
             requestMap.put("meta", meta_re);
             requestMap = serializer.addParameters(requestMap, page, num,
                     cli, cri, cls, crs);
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
index bd55641..4b74ce4 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/MetaCollectionSerializer.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/MetaCollectionSerializer.java
@@ -1,5 +1,8 @@
 package de.ids_mannheim.korap.query.serialize;
 
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 
 import java.io.IOException;
@@ -12,6 +15,7 @@
  * @author hanl
  * @date 04/12/2013
  */
+@Deprecated
 public class MetaCollectionSerializer {
 
     public String meta1 = "{\n" +
@@ -85,15 +89,19 @@
     }
 
     //resources must be ordered: 0 without parent, 1 has 0 as parent, etc.
-    public List<ArrayList> serializeResource(List<String> r_queries) throws IOException {
+    public List<Map> serializeResource(List<String> r_queries) throws IOException {
+        JsonFactory factory = mapper.getFactory();
         List parids = new ArrayList<>();
         for (String query : r_queries) {
-            ArrayList m = mapper.readValue(query, ArrayList.class);
-            parids.add(m);
+            JsonParser jp = factory.createParser(query);
+            JsonNode m = jp.readValueAsTree();
+            for (JsonNode n : m)
+                parids.add(mapper.treeToValue(n, Map.class));
         }
         return parids;
     }
 
+    @Deprecated
     private Map<String, String> getParents(String id) {
         Map<String, String> cursor = getResource(id);
         Map<String, String> parents = new HashMap<>();
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/MetaQuery.java b/src/main/java/de/ids_mannheim/korap/query/serialize/MetaQuery.java
new file mode 100644
index 0000000..3547d82
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/MetaQuery.java
@@ -0,0 +1,286 @@
+package de.ids_mannheim.korap.query.serialize;
+
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Multimap;
+
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * @author hanl
+ * @date 06/12/2013
+ */
+public class MetaQuery {
+
+    private JsonFactory factory;
+    private MetaTypes types;
+    private ObjectMapper serialzer;
+    private List<Map> rq;
+    private List<Map> mfil;
+    private List<Map> mext;
+    private Multimap<Integer, Integer> track;
+
+    public MetaQuery() {
+        this.serialzer = new ObjectMapper();
+        this.rq = new ArrayList<>();
+        this.mfil = new ArrayList<>();
+        this.mext = new ArrayList<>();
+        this.factory = serialzer.getFactory();
+        this.types = new MetaTypes();
+        this.track = ArrayListMultimap.create();
+    }
+
+    public MetaQuery addResource(String query) throws IOException {
+        JsonParser jp = factory.createParser(query);
+        JsonNode m = jp.readValueAsTree();
+        for (JsonNode n : m)
+            this.rq.add(serialzer.treeToValue(n, Map.class));
+        return this;
+    }
+
+    public MetaQuery addResources(List<String> queries) throws IOException {
+        for (String query : queries) {
+            JsonParser jp = factory.createParser(query);
+            JsonNode m = jp.readValueAsTree();
+            for (JsonNode n : m)
+                this.rq.add(serialzer.treeToValue(n, Map.class));
+        }
+        return this;
+    }
+
+    public MetaQuery addMetaFilter(Map<String, String> queries) {
+        //single is redundant!
+        boolean single = true;
+        boolean multypes = queries.keySet().size() > 1;
+        String def_key = null;
+        if (queries.size() > 1)
+            single = false;
+
+        List value = new ArrayList<>();
+        List<String> dates = new ArrayList<>();
+        for (String key : queries.keySet()) {
+            if (!multypes)
+                def_key = key;
+            if (queries.get(key).contains("~") | queries.get(key).contains(">") |
+                    queries.get(key).contains("<")) {
+                dates.add(queries.get(key));
+                continue;
+            }
+
+            Map term;
+            term = types.createTerm(key, null, queries.get(key).trim(), null);
+            value.add(term);
+        }
+
+        String[] proc = processDates(dates);
+        int idx = 3;
+        if (proc[0] != null && proc[0].equals("r")) {
+            Map term1 = types.createTerm(proc[1], "korap:date");
+            Map term2 = types.createTerm(proc[2], "korap:date");
+            Map group = types.createGroup("between", "pubDate", Arrays.asList(term1, term2));
+            value.add(group);
+        } else if (proc[1] != null) {
+            Map term1 = types.createTerm(proc[1], "korap:date");
+            Map group = types.createGroup("since", "pubDate", Arrays.asList(term1));
+            value.add(group);
+        } else if (proc[2] != null) {
+            Map term1 = types.createTerm(proc[2], "korap:date");
+            Map group = types.createGroup("until", "pubDate", Arrays.asList(term1));
+            value.add(group);
+        }
+
+
+        for (int i = idx; i < proc.length; i++) {
+            if (proc[i] != null) {
+                Map term1 = types.createTerm(proc[i], "korap:date");
+                Map group = types.createGroup("until", "pubDate", Arrays.asList(term1));
+                value.add(group);
+            }
+        }
+
+        // todo: missing: - takes only one resource, but resources can be chained!
+        if (single)
+            Collections.addAll(this.mfil, 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);
+            Collections.addAll(this.mfil, types.createMetaFilter(group));
+        }
+        return this;
+    }
+
+    public MetaQuery addMetaExtend(Map<String, String> queries) {
+        //single is redundant!
+        boolean single = true;
+        boolean multypes = queries.keySet().size() > 1;
+
+        //!an extend to a non-existing filter is not possible
+        if (this.mfil.isEmpty())
+            throw new IllegalArgumentException("Extending Query " +
+                    "cannot be added before Filter!");
+
+        String def_key = null;
+        if (queries.size() > 1)
+            single = false;
+
+        List value = new ArrayList<>();
+        List<String> dates = new ArrayList<>();
+        for (String key : queries.keySet()) {
+            if (!multypes)
+                def_key = key;
+            if (queries.get(key).contains("~") | queries.get(key).contains(">") |
+                    queries.get(key).contains("<")) {
+                dates.add(queries.get(key));
+                continue;
+            }
+            value.add(types.createTerm(key, null, queries.get(key).trim(), null));
+        }
+
+        String[] proc = processDates(dates);
+        int idx = 3;
+        if (proc[0] != null && proc[0].equals("r")) {
+            Map term1 = types.createTerm(proc[1], "korap:date");
+            Map term2 = types.createTerm(proc[2], "korap:date");
+            Map group = types.createGroup("between", "pubDate", Arrays.asList(term1, term2));
+            value.add(group);
+        } else if (proc[1] != null) {
+            Map term1 = types.createTerm(proc[1], "korap:date");
+            Map group = types.createGroup("since", "pubDate", Arrays.asList(term1));
+            value.add(group);
+        } else if (proc[2] != null) {
+            Map term1 = types.createTerm(proc[2], "korap:date");
+            Map group = types.createGroup("until", "pubDate", Arrays.asList(term1));
+            value.add(group);
+        }
+
+
+        for (int i = idx; i < proc.length; i++) {
+            if (proc[i] != null) {
+                Map term1 = types.createTerm(proc[i], "korap:date");
+                Map group = types.createGroup("until", "pubDate", Arrays.asList(term1));
+                value.add(group);
+            }
+        }
+        // todo: missing: - takes only one resource, but resources can be chained!
+        if (single)
+            Collections.addAll(this.mext, types.createMetaExtend((Map) value.get(0)));
+        else {
+            Map group;
+            if (!multypes)
+                group = types.createGroup("and", def_key, value);
+            else
+                group = types.createGroup("and", null, value);
+            Collections.addAll(this.mext, types.createMetaExtend(group));
+        }
+        track.put(this.mfil.size() - 1, this.mext.size() - 1);
+
+        return this;
+    }
+
+    public MetaQuery addMetaFilter(String attr, String val) {
+        Map y = new HashMap<>();
+        y.put(attr, val);
+        return addMetaFilter(y);
+    }
+
+    public MetaQuery addMetaExtend(String attr, String val) {
+        Map y = new HashMap<>();
+        y.put(attr, val);
+        return addMetaExtend(y);
+    }
+
+    private String[] processDates(List<String> dates) {
+        if (dates.isEmpty())
+            return new String[3];
+        boolean range = false;
+        String[] el = new String[dates.size() + 3];
+        int idx = 3;
+        for (String value : dates) {
+            if (value.contains("<")) {
+                String[] sp = value.split("<");
+                el[1] = types.formatDate(Long.valueOf(sp[1]), MetaTypes.YMD);
+            } else if (value.contains(">")) {
+                String[] sp = value.split(">");
+                el[2] = types.formatDate(Long.valueOf(sp[1]), MetaTypes.YMD);
+            } else if (value.contains("~")) {
+                range = true;
+                String[] sp = value.split("~");
+                el[1] = types.formatDate(Long.valueOf(sp[0]), MetaTypes.YMD);
+                el[2] = types.formatDate(Long.valueOf(sp[1]), MetaTypes.YMD);
+            } else {
+                el[idx] = types.formatDate(Long.valueOf(value), MetaTypes.YMD);
+                idx++;
+            }
+        }
+        if (range)
+            el[0] = "r";
+        return el;
+    }
+
+    public void clear() {
+        this.rq.clear();
+        this.mfil.clear();
+    }
+
+    @Deprecated
+    //todo: ordering irrelevant
+    private List<Map> join() {
+        List<Map> cursor = new ArrayList<>(this.rq);
+        List<Map> copy = new ArrayList<>();
+        if (!this.mext.isEmpty()) {
+            for (int idx = 0; idx < this.mfil.size(); idx++) {
+                copy.add(idx, this.mfil.get(idx));
+                if (!this.track.get(idx).isEmpty()) {
+                    Collection<Integer> ext = this.track.get(idx);
+                    for (Integer i : ext)
+                        copy.add(this.mext.get(i));
+                }
+            }
+        } else
+            copy = this.mfil;
+        cursor.addAll(copy);
+        return cursor;
+    }
+
+    private List<Map> join2() {
+        List<Map> cursor = new ArrayList<>(this.rq);
+        cursor.addAll(this.mfil);
+        cursor.addAll(this.mext);
+        return cursor;
+    }
+
+    public String stringify() {
+        try {
+            return serialzer.writeValueAsString(join2());
+        } catch (JsonProcessingException e) {
+            e.printStackTrace();
+            return "";
+        }
+    }
+
+    public JsonNode jsonify() {
+        return serialzer.valueToTree(join2());
+    }
+
+    public String toMeta() {
+        Map meta = new LinkedHashMap();
+        meta.put("meta", join2());
+
+        try {
+            return serialzer.writeValueAsString(meta);
+        } catch (JsonProcessingException e) {
+            e.printStackTrace();
+            return "";
+        }
+    }
+
+
+}
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
index ba0cd8a..5cca176 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/MetaQuerySerializer.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/MetaQuerySerializer.java
@@ -16,6 +16,7 @@
  * Date: 11/14/13
  * Time: 2:03 PM
  */
+@Deprecated
 public class MetaQuerySerializer {
 
 
@@ -68,7 +69,7 @@
         //single is redundant!
         boolean extend, single = true; //single = true;
         boolean multypes = queries.keySet().size() > 1;
-        List<Map> metavalue;
+        List<Map> metavalue = new ArrayList<>();
         String def_key = null;
         if (queries.size() > 1)
             single = false;
@@ -150,21 +151,22 @@
         // todo: missing: - takes only one resource, but resources can be chained!
         if (single) {
             if (extend)
-                metavalue = Arrays.asList(types.createMetaExtend((Map) value.get(0)));
+                Collections.addAll(metavalue, types.createMetaExtend((Map) value.get(0)));
             else
-                metavalue = Arrays.asList(types.createMetaFilter((Map) value.get(0)));
+                Collections.addAll(metavalue, 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 = Arrays.asList(types.createMetaExtend(group));
             if (extend)
-                metavalue = Arrays.asList(types.createMetaExtend(group));
+                Collections.addAll(metavalue, types.createMetaExtend(group));
             else
-                metavalue = Arrays.asList(types.createMetaFilter(group));
+                Collections.addAll(metavalue, types.createMetaFilter(group));
         }
-        return new ArrayList<>(metavalue);
+        return metavalue;
     }
 
     //fixme: only allows for one until and since entry!!
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/Serializer.java b/src/main/java/de/ids_mannheim/korap/query/serialize/Serializer.java
index 8edf09d..f800e68 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/Serializer.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/Serializer.java
@@ -10,6 +10,7 @@
  * @author hanl
  * @date 05/12/2013
  */
+@Deprecated
 public class Serializer {
 
 
@@ -30,14 +31,21 @@
         return mapper.writeValueAsString(metas);
     }
 
-    public String stringify(List m_queries) throws JsonProcessingException {
-        return mapper.writeValueAsString(m_queries);
+    public String stringify(Object object) throws JsonProcessingException {
+        return mapper.writeValueAsString(object);
     }
 
-    public List<ArrayList> serializeResources(List<String> r_queries) throws IOException {
+    public List<Map> serializeResources(List<String> r_queries) throws IOException {
         return cs.serializeResource(r_queries);
     }
 
+    public String queryToMeta(String s) throws IOException {
+        Map f = new HashMap();
+        List e = mapper.readValue(s, ArrayList.class);
+        f.put("meta", e);
+        return mapper.writeValueAsString(f);
+    }
+
     public List<Map> serializeQueries(Map<String, String> queries, MetaQuerySerializer.TYPE type) {
         return qs.serializeQueries(queries, type);
     }