Introduce match aggregator for paging results

Change-Id: I649322457a39e098933317fac4b35061e37a9ebe
diff --git a/plugin/src/main/java/de/ids_mannheim/korap/plkexport/MatchAggregator.java b/plugin/src/main/java/de/ids_mannheim/korap/plkexport/MatchAggregator.java
new file mode 100644
index 0000000..19e4709
--- /dev/null
+++ b/plugin/src/main/java/de/ids_mannheim/korap/plkexport/MatchAggregator.java
@@ -0,0 +1,130 @@
+package de.ids_mannheim.korap.plkexport;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.Collection;
+import java.util.ArrayList;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.Version;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+
+public class MatchAggregator implements Iterable<JsonNode> {
+
+    private ObjectMapper mapper = new ObjectMapper();
+
+    private LinkedList<JsonNode> matches;
+
+    private BufferedWriter writer;
+
+    public JsonNode meta, query, collection;
+
+    /**
+     * Create new match aggregator and parse initial Json
+     * file to get header information and initial matches.
+     */
+    public MatchAggregator (String resp) throws IOException {
+
+        JsonParser parser = mapper.getFactory().createParser(resp);
+        JsonNode actualObj = mapper.readTree(parser);
+
+        if (actualObj == null)
+            return;
+
+        this.meta       = actualObj.get("meta");
+        this.query      = actualObj.get("query");
+        this.collection = actualObj.get("collection");
+
+
+        JsonNode mNodes = actualObj.get("matches");
+
+        if (mNodes == null)
+            return;
+        
+        // Iterate over the results of the current file
+        Iterator<JsonNode> mNode = mNodes.elements();
+        matches = new LinkedList();
+        while (mNode.hasNext()) {
+            this.matches.add(mNode.next());
+        };
+    };
+
+    /**
+     * Append more matches to the result set.
+     */
+    public void append (String resp) throws IOException {
+
+        // Open a temp file if not already opened
+        if (writer == null) {
+
+            // Create temporary file
+            File expTmp = File.createTempFile("idsexppl-", ".tmpJson");
+
+            // better delete after it is not needed anymore
+            expTmp.deleteOnExit();
+
+            // Establish writer
+            writer = new BufferedWriter(new FileWriter(expTmp, true));
+        };
+
+        JsonParser parser = mapper.getFactory().createParser(resp);
+        JsonNode actualObj = mapper.readTree(parser);
+        Iterator<JsonNode> mNode = actualObj.get("matches").elements();
+
+        MatchExport match;
+        while (mNode.hasNext()) {
+            writer.append(mNode.next().toString());
+            writer.newLine();
+        };
+    };
+
+    /**
+     * Return an iterator for all matches
+     */
+    public Iterator<JsonNode> iterator() { 
+        return new MatchIterator(); 
+    };
+
+
+    // Private iterator class
+    private class MatchIterator implements Iterator<JsonNode> {
+        private int listIndex, fileIndex;
+
+        // Constructor
+        public MatchIterator () {
+            this.listIndex = matches.size() > 0 ? 0 : -1;
+
+            // Set to zero, if file exists
+            this.fileIndex = (writer != null) ? 0 : -1;
+        };
+
+        @Override
+        public boolean hasNext () {
+            if (listIndex >= 0 || fileIndex >= 0) {
+                return true;
+            };
+            return false;
+        };
+
+        @Override
+        public JsonNode next () {
+            if (this.listIndex > 0) {
+                int i = this.listIndex;
+                if (i >= matches.size()) {
+                    this.listIndex = -1;
+                };
+                return matches.get(i);
+            };
+            return null;
+        };
+    };
+};
diff --git a/plugin/src/test/java/de/ids_mannheim/korap/plkexport/MatchAggregatorTest.java b/plugin/src/test/java/de/ids_mannheim/korap/plkexport/MatchAggregatorTest.java
new file mode 100644
index 0000000..a819414
--- /dev/null
+++ b/plugin/src/test/java/de/ids_mannheim/korap/plkexport/MatchAggregatorTest.java
@@ -0,0 +1,32 @@
+package de.ids_mannheim.korap.plkexport;
+
+import java.io.IOException;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import org.junit.Test;
+
+import de.ids_mannheim.korap.plkexport.MatchAggregator;
+
+public class MatchAggregatorTest {
+
+    @Test
+    public void testEmptyInit () throws IOException {
+        MatchAggregator m = new MatchAggregator("");
+        assertNull(m.meta);
+        assertNull(m.query);
+        assertNull(m.collection);
+    };
+
+    @Test
+    public void testSampleInit () throws IOException {
+        MatchAggregator m = new MatchAggregator(
+            "{\"meta\":{\"totalResults\":6}}"
+            );
+        assertEquals(m.meta.toString(),"{\"totalResults\":6}");
+        assertNull(m.query);
+        assertNull(m.collection);
+    };
+};