package ctbrec.io; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.time.Instant; 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.SubsequentAction; import ctbrec.sites.Site; import ctbrec.sites.chaturbate.ChaturbateModel; public class ModelJsonAdapter extends JsonAdapter { private static final 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; Object type = null; int streamUrlIndex = -1; int priority; 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("type")) { type = reader.readJsonValue(); Class modelClass = Class.forName(Optional.ofNullable(type).orElse(ChaturbateModel.class.getName()).toString()); model = (Model) modelClass.getDeclaredConstructor().newInstance(); } else 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("priority")) { priority = reader.nextInt(); model.setPriority(priority); } 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("lastSeen")) { model.setLastSeen(Instant.ofEpochMilli(reader.nextLong())); } else if(key.equals("lastRecorded")) { model.setLastRecorded(Instant.ofEpochMilli(reader.nextLong())); } else if(key.equals("recordUntil")) { model.setRecordUntil(Instant.ofEpochMilli(reader.nextLong())); } else if(key.equals("recordUntilSubsequentAction")) { model.setRecordUntilSubsequentAction(SubsequentAction.valueOf(reader.nextString())); } 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("priority").value(model.getPriority()); writer.name("streamUrlIndex").value(model.getStreamUrlIndex()); writer.name("suspended").value(model.isSuspended()); writer.name("lastSeen").value(model.getLastSeen().toEpochMilli()); writer.name("lastRecorded").value(model.getLastRecorded().toEpochMilli()); writer.name("recordUntil").value(model.getRecordUntil().toEpochMilli()); writer.name("recordUntilSubsequentAction").value(model.getRecordUntilSubsequentAction().name()); 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); } } }