package ctbrec.io; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.List; import java.util.Optional; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.squareup.moshi.JsonAdapter; import com.squareup.moshi.JsonReader; import com.squareup.moshi.JsonReader.Token; import com.squareup.moshi.JsonWriter; import ctbrec.Model; import ctbrec.sites.Site; import ctbrec.sites.chaturbate.ChaturbateModel; public class ModelJsonAdapter extends JsonAdapter { private static final transient Logger LOG = LoggerFactory.getLogger(ModelJsonAdapter.class); private List sites; public ModelJsonAdapter() { } public ModelJsonAdapter(List sites) { this.sites = sites; } @Override public Model fromJson(JsonReader reader) throws IOException { reader.beginObject(); String name = null; String description = null; String url = null; String type = null; int streamUrlIndex = -1; boolean suspended = false; Model model = null; while(reader.hasNext()) { try { Token token = reader.peek(); if(token == Token.NAME) { String key = reader.nextName(); if(key.equals("name")) { name = reader.nextString(); model.setName(name); } else if(key.equals("description")) { description = reader.nextString(); model.setDescription(description); } else if(key.equals("url")) { url = reader.nextString(); model.setUrl(url); } else if(key.equals("type")) { type = reader.nextString(); Class modelClass = Class.forName(Optional.ofNullable(type).orElse(ChaturbateModel.class.getName())); model = (Model) modelClass.getDeclaredConstructor().newInstance(); } else if(key.equals("streamUrlIndex")) { streamUrlIndex = reader.nextInt(); model.setStreamUrlIndex(streamUrlIndex); } else if(key.equals("suspended")) { suspended = reader.nextBoolean(); model.setSuspended(suspended); } else if(key.equals("siteSpecific")) { reader.beginObject(); try { model.readSiteSpecificData(reader); } catch(Exception e) { LOG.error("Couldn't read site specific data for model {}", model.getName()); throw e; } reader.endObject(); } } else { reader.skipValue(); } } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) { throw new IOException("Couldn't instantiate model class [" + type + "]", e); } } reader.endObject(); if(sites != null) { for (Site site : sites) { if(site.isSiteForModel(model)) { model.setSite(site); } } } return model; } @Override public void toJson(JsonWriter writer, Model model) throws IOException { writer.beginObject(); writer.name("type").value(model.getClass().getName()); writeValueIfSet(writer, "name", model.getName()); writeValueIfSet(writer, "description", model.getDescription()); writeValueIfSet(writer, "url", model.getUrl()); writer.name("streamUrlIndex").value(model.getStreamUrlIndex()); writer.name("suspended").value(model.isSuspended()); writer.name("siteSpecific"); writer.beginObject(); model.writeSiteSpecificData(writer); writer.endObject(); writer.endObject(); } private void writeValueIfSet(JsonWriter writer, String name, String value) throws IOException { if(value != null) { writer.name(name).value(value); } } }