Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding JSON Iterator and removing unnecessary imports #5

Merged
merged 1 commit into from
Nov 27, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public class JsonFileReader {
* @return List of JSON lines from the file
* @throws IOException thrown if there is a problem accessing the file
*/
public static List<Map<String, Object>> readJsonFromResource(String resourceName) throws IOException {
public static List<Map<String, Object>> readJsonFromResource(final String resourceName) throws IOException {
List<Map<String, Object>> jsonList = new ArrayList<>();
String json;
try (BufferedReader br = new BufferedReader(
Expand All @@ -46,7 +46,7 @@ public static List<Map<String, Object>> readJsonFromResource(String resourceName
* @return List of JSON lines from the file
* @throws IOException thrown if there is a problem accessing the file
*/
public static List<Map<String, Object>> readJsonFromFile(String fileName) throws IOException {
public static List<Map<String, Object>> readJsonFromFile(final String fileName) throws IOException {
List<Map<String, Object>> jsonList = new ArrayList<>();
for (String json : getFileLines(fileName)) {
jsonList.add(gson.fromJson(json, HashMap.class));
Expand All @@ -61,7 +61,7 @@ public static List<Map<String, Object>> readJsonFromFile(String fileName) throws
* @return List of lines from the file
* @throws IOException thrown if there is a problem accessing the file
*/
public static List<String> getFileLines(String fileName) throws IOException {
public static List<String> getFileLines(final String fileName) throws IOException {
List<String> text = new ArrayList<>();
try (BufferedReader br = new BufferedReader(new FileReader(fileName))) {
String line;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package com.caffinc.jaggr.utils;

import com.google.gson.Gson;

import java.io.*;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;

/**
* Iterates a JSON file
*
* @author Sriram
* @since 11/27/2016
*/
public class JsonIterator implements Iterator<Map<String, Object>>, Closeable {
private final BufferedReader bufferedReader;
private String cachedLine;
private boolean finished = false;
private Gson gson = new Gson();

/**
* Constructs an iterator of the lines for a <code>fileName</code>.
*
* @param fileName the <code>fileName</code> to read from
* @throws IOException thrown if there is a problem accessing the file
*/
public JsonIterator(final String fileName) throws IOException {
this(new BufferedReader(new FileReader(fileName)));
}

/**
* Constructs an iterator of the lines for a <code>Reader</code>.
*
* @param reader the <code>Reader</code> to read from, not null
* @throws IllegalArgumentException if the reader is null
*/
public JsonIterator(final Reader reader) throws IllegalArgumentException {
if (reader == null) {
throw new IllegalArgumentException("Reader must not be null");
}
if (reader instanceof BufferedReader) {
bufferedReader = (BufferedReader) reader;
} else {
bufferedReader = new BufferedReader(reader);
}
}

/**
* Indicates whether the <code>Reader</code> has more lines.
* If there is an <code>IOException</code> then {@link #close()} will
* be called on this instance.
*
* @return {@code true} if the Reader has more lines
* @throws IllegalStateException if an IO exception occurs
*/
public boolean hasNext() {
if (cachedLine != null) {
return true;
} else if (finished) {
return false;
} else {
try {
while (true) {
final String line = bufferedReader.readLine();
if (line == null) {
finished = true;
return false;
}
cachedLine = line;
return true;
}
} catch (final IOException ioe) {
close();
throw new IllegalStateException(ioe);
}
}
}

/**
* Returns the next object in the file or wrapped <code>Reader</code>.
*
* @return the next JSON object from the input
* @throws NoSuchElementException if there is no object to return
*/
public Map<String, Object> next() {
return nextObject();
}

/**
* Returns the next object in the file or wrapped <code>Reader</code>.
*
* @return the next JSON object from the input
* @throws NoSuchElementException if there is no object to return
*/
public Map<String, Object> nextObject() {
if (!hasNext()) {
throw new NoSuchElementException("No more objects");
}
final String currentLine = cachedLine;
cachedLine = null;
return gson.fromJson(currentLine, HashMap.class);
}

/**
* Closes the underlying <code>Reader</code> quietly.
* This method is useful if you only want to process the first few
* lines of a larger file. If you do not close the iterator
* then the <code>Reader</code> remains open.
* This method can safely be called multiple times.
*/
public void close() {
finished = true;
try {
bufferedReader.close();
} catch (final IOException ioe) {
// ignore
}
cachedLine = null;
}

/**
* Unsupported.
*
* @throws UnsupportedOperationException always
*/
public void remove() {
throw new UnsupportedOperationException("Remove unsupported on JsonIterator");
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.caffinc.jaggr.utils;

import com.google.gson.Gson;
import org.junit.Assert;
import org.junit.Test;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;

/**
* Tests for the JsonIterator
*
* @author Sriram
* @since 11/27/2016
*/
public class JsonIteratorTest {
private static final String TEMP_DIR = System.getProperty("java.io.tmpdir");
private static final Random RANDOM = new Random();
private static final Gson GSON = new Gson();

@Test
public void testJsonFileIterator() throws Exception {
Path tempFilePath = Paths.get(TEMP_DIR, "jsontest" + RANDOM.nextInt() + ".json");
try {
List<Map<String, Object>> expectedData = new ArrayList<>();
try (BufferedWriter br = new BufferedWriter(new FileWriter(tempFilePath.toFile()))
) {
for (int i = 0; i < 10; i++) {
Map<String, Object> json = new HashMap<>();
json.put("_id", (double) i);
json.put("val", RANDOM.nextDouble());
expectedData.add(json);
br.write(GSON.toJson(json) + "\n");
}
}
try (JsonIterator jsonIterator = new JsonIterator(tempFilePath.toString())) {
for (Map<String, Object> expected : expectedData) {
Map<String, Object> actual = jsonIterator.next();
Assert.assertEquals("Value should match value written to file", expected, actual);
}
}
} finally {
Files.delete(tempFilePath);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,12 @@ public List<Map<String, Object>> aggregate(Iterator<Map<String, Object>> objectI
}

/**
* Aggregates over a list of JSON Objects
* Aggregates over an iterable list of JSON Objects
*
* @param objectList JSON Object list
* @param objectList Iterable list of JSON Objects
* @return aggregation result
*/
public List<Map<String, Object>> aggregate(List<Map<String, Object>> objectList) {
public List<Map<String, Object>> aggregate(Iterable<Map<String, Object>> objectList) {
Map<String, Map<String, Object>> workspace = new HashMap<>();
if (objectList != null) {
for (Map<String, Object> object : objectList) {
Expand Down