denominator.dynect.DynECTAdapters Maven / Gradle / Ivy
package denominator.dynect;
import static denominator.common.Preconditions.checkState;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonIOException;
import com.google.gson.JsonParser;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import denominator.dynect.DynECT.Data;
import denominator.dynect.DynECT.Record;
import denominator.model.Zone;
/**
* DynECT json includes an envelope called "data". These type adapters apply at
* that level.
*
* @see DynECTDecoder
*/
class DynECTAdapters {
private DynECTAdapters() {
// no instances.
}
static class NothingForbiddenAdapter extends DataAdapter {
@Override
public Boolean build(JsonReader reader) throws IOException {
try {
return new JsonParser().parse(reader).getAsJsonObject().get("forbidden").getAsJsonArray().size() == 0;
} catch (JsonIOException e) {
if (e.getCause() != null && e.getCause() instanceof IOException) {
throw IOException.class.cast(e.getCause());
}
throw e;
}
}
}
static class TokenAdapter extends DataAdapter {
@Override
public String build(JsonReader reader) throws IOException {
try {
return new JsonParser().parse(reader).getAsJsonObject().get("token").getAsString();
} catch (JsonIOException e) {
if (e.getCause() != null && e.getCause() instanceof IOException) {
throw IOException.class.cast(e.getCause());
}
throw e;
}
}
}
static class ZonesAdapter extends DataAdapter> {
@Override
public List build(JsonReader reader) throws IOException {
JsonArray data;
try {
data = new JsonParser().parse(reader).getAsJsonArray();
} catch (JsonIOException e) {
if (e.getCause() != null && e.getCause() instanceof IOException) {
throw IOException.class.cast(e.getCause());
}
throw e;
}
List zones = new ArrayList();
for (String name : toFirstGroup("/REST.*/([^/]+)/?$", data)) {
zones.add(Zone.create(name));
}
return zones;
}
}
static class RecordIdsAdapter extends DataAdapter> {
@Override
public List build(JsonReader reader) throws IOException {
JsonArray data;
try {
data = new JsonParser().parse(reader).getAsJsonArray();
} catch (JsonIOException e) {
if (e.getCause() != null && e.getCause() instanceof IOException) {
throw IOException.class.cast(e.getCause());
}
throw e;
}
return toFirstGroup("/REST/([a-zA-Z]+Record/[^\"]+/[^\"]+/[0-9]+)", data);
}
}
static class RecordsByNameAndTypeAdapter extends DataAdapter> {
@Override
public Iterator build(JsonReader reader) throws IOException {
JsonArray data;
try {
data = new JsonParser().parse(reader).getAsJsonArray();
} catch (JsonIOException e) {
if (e.getCause() != null && e.getCause() instanceof IOException) {
throw IOException.class.cast(e.getCause());
}
throw e;
}
List records = new ArrayList();
for (JsonElement datum : data) {
records.add(ToRecord.INSTANCE.apply(datum));
}
return records.iterator();
}
}
private static List toFirstGroup(String pattern, JsonArray elements) {
Pattern compiled = Pattern.compile(pattern);
List results = new ArrayList(elements.size());
for (JsonElement in : elements) {
Matcher matcher = compiled.matcher(in.getAsString());
checkState(matcher.find() && matcher.groupCount() == 1, "%s didn't match %s", in, compiled);
results.add(matcher.group(1));
}
return results;
}
static abstract class DataAdapter extends TypeAdapter> {
protected abstract X build(JsonReader reader) throws IOException;
@Override
public Data read(JsonReader reader) throws IOException {
Data data = new Data();
reader.beginObject();
while (reader.hasNext()) {
String nextName = reader.nextName();
if ("data".equals(nextName)) {
data.data = build(reader);
} else {
reader.skipValue();
}
}
reader.endObject();
reader.close();
return data;
}
@Override
public void write(JsonWriter out, Data value) throws IOException {
throw new UnsupportedOperationException();
}
}
}