package eu.ehri.project.indexing.source.impl;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import eu.ehri.project.indexing.source.Source;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
public class InputStreamJsonSource implements Source<JsonNode> {
private static final ObjectMapper mapper = new ObjectMapper();
private static final JsonFactory jsonFactory = new JsonFactory().setCodec(mapper);
private final InputStream ios;
private JsonParser jsonParser;
private boolean finished = false;
public InputStreamJsonSource(InputStream ios) {
this.ios = ios;
}
public void close() throws SourceException {
finished = true;
if (jsonParser != null) {
try {
jsonParser.close();
} catch (IOException e) {
throw new RuntimeException("Error closing JSON parser", e);
}
}
}
@Override
public Iterable<JsonNode> iterable() throws SourceException {
try {
jsonParser = jsonFactory.createParser(ios);
JsonToken firstToken = jsonParser.nextValue();
if (!jsonParser.isExpectedStartArrayToken()) {
throw new SourceException("Excepted a JSON array, instead first token was: " + firstToken);
}
// NB: Since the iterator is run lazily, a parse error here will
// not be caught and instead throw a RuntimeException "Unexpected character..."
// I'm not sure how we can fix that.
if (jsonParser.nextValue() == JsonToken.END_ARRAY) {
return Lists.newArrayListWithExpectedSize(0);
} else {
final Iterator<JsonNode> iterator = jsonParser.readValuesAs(JsonNode.class);
return new Iterable<JsonNode>() {
@Override
public Iterator<JsonNode> iterator() {
return iterator;
}
};
}
} catch (IOException e) {
throw new SourceException("Error reading JSON stream: ", e);
}
}
@Override
public boolean isFinished() {
return finished;
}
}