package com.gettingmobile.google.reader.rest;
import com.gettingmobile.rest.ContentIOException;
import com.gettingmobile.rest.entity.JsonAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.Closeable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public abstract class JsonStream<T> implements Iterator<T>, Closeable {
protected final JsonReader reader;
private final JsonAdapter<T> adapter;
private boolean hasNext = false;
protected JsonStream(JsonReader reader, JsonAdapter<T> adapter) {
this.reader = reader;
this.adapter = adapter;
}
protected void startReading() throws IOException {
hasNext = readArrayStart() && hasNextObjectStart();
if (!hasNext()) {
readToEnd();
}
}
public List<T> readAsList() {
final List<T> list = new ArrayList<T>();
while (hasNext()) {
list.add(next());
}
return list;
}
@Override
public boolean hasNext() {
return hasNext;
}
protected boolean isExceptionRecoverable(Exception ex) {
return false;
}
protected void prepareNext() throws IOException {
hasNext = hasNextObjectStart();
if (!hasNext()) {
readToEnd();
}
}
@Override
public T next() {
T next = null;
JsonStreamException error = null;
try {
next = readNextObject();
} catch (JsonStreamException ex) {
error = ex;
} catch (Exception ex) {
error = new JsonStreamException(ex, isExceptionRecoverable(ex));
}
if (error == null || error.isRecoverable()) {
try {
prepareNext();
} catch (IOException ex) {
throw error != null ? error : new JsonStreamException(ex, false);
}
}
if (error != null)
throw error;
return next;
}
@Override
public void remove() {
throw new UnsupportedOperationException("JsonStream.remove does not make sense");
}
@Override
public void close() throws IOException {
hasNext = false;
reader.close();
}
protected abstract boolean readArrayStart() throws IOException;
protected boolean hasNextObjectStart() throws IOException {
return reader.hasNext() && reader.peek() == JsonToken.BEGIN_OBJECT;
}
protected T readNextObject() throws IOException, JSONException {
return readObject(JsonObjectReader.readObject(reader));
}
protected T readObject(JSONObject json) throws JSONException, ContentIOException {
return adapter.read(json);
}
protected void readToEnd() throws IOException {
reader.close();
}
}