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(); Object type = null; 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")) { model.setName(reader.nextString()); } else if (key.equals("description")) { model.setDescription(reader.nextString()); } else if (key.equals("url")) { model.setUrl(reader.nextString()); } else if (key.equals("priority")) { model.setPriority(reader.nextInt()); } else if (key.equals("streamUrlIndex")) { model.setStreamUrlIndex(reader.nextInt()); } else if (key.equals("suspended")) { model.setSuspended(reader.nextBoolean()); } else if (key.equals("markedForLater")) { model.setMarkedForLaterRecording(reader.nextBoolean()); } 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("markedForLater").value(model.isMarkedForLaterRecording()); 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); } } }