package com.datascience.serialization.json;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import com.datascience.core.base.*;
import com.datascience.core.commands.Utils;
import com.datascience.core.commands.Utils.ShallowAssign;
import com.datascience.datastoring.datamodels.memory.InMemoryData;
import com.datascience.core.nominal.CategoryValue;
import com.datascience.datastoring.datamodels.memory.InMemoryNominalData;
import com.datascience.core.results.ResultsFactory;
import com.datascience.core.stats.MatrixValue;
import com.datascience.utils.CostMatrix;
import com.google.gson.*;
import com.google.gson.reflect.TypeToken;
/**
* @Author: konrad
*/
public class DataJSON {
private static abstract class Deserializer<T> implements JsonDeserializer<InMemoryData<T>> {
public abstract Type getLObjectType();
public abstract Type getShallowAssignType();
@Override
public InMemoryData<T> deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
InMemoryData<T> data = new InMemoryData<T>();
JsonObject jo = jsonElement.getAsJsonObject();
for (JsonElement je: jo.get("objects").getAsJsonArray()){
LObject<T> object = jsonDeserializationContext.deserialize(je, getLObjectType());
data.addObject(object);
}
for (JsonElement je: jo.get("assigns").getAsJsonArray()){
Utils.ShallowAssign<T> sassign = jsonDeserializationContext.deserialize(je, getShallowAssignType());
Worker worker = data.getOrCreateWorker(sassign.worker);
LObject<T> object = data.getObject(sassign.object);
data.addAssign(new AssignedLabel<T>(worker, object, sassign.label));
}
return data;
}
}
public static class ContValueDataDeserializer extends Deserializer<ContValue>{
@Override
public Type getLObjectType() {
return new TypeToken<LObject<ContValue>>(){}.getType();
}
@Override
public Type getShallowAssignType() {
return new TypeToken<Utils.ShallowAssign<ContValue>>(){}.getType();
}
}
public static class StringDataDeserializer extends Deserializer<String>{
@Override
public Type getLObjectType() {
return new TypeToken<LObject<String>>(){}.getType();
}
@Override
public Type getShallowAssignType() {
return new TypeToken<Utils.ShallowAssign<String>>(){}.getType();
}
}
public static class NominalDeserializer implements JsonDeserializer<InMemoryNominalData> {
@Override
public InMemoryNominalData deserialize(JsonElement element, Type type, JsonDeserializationContext context) throws JsonParseException {
Deserializer<String> deserializer = new StringDataDeserializer();
InMemoryNominalData ret = new InMemoryNominalData(deserializer.deserialize(element, type, context));
JsonObject jo = element.getAsJsonObject();
ret.initialize(
(Collection<String>) context.deserialize(jo.get("categories"), JSONUtils.stringSetType),
jo.has("categoryPriors") ? (Collection<CategoryValue>) context.deserialize(jo.get("categoryPriors"), JSONUtils.categoryValuesCollectionType) : null,
jo.has("costMatrix") ? (CostMatrix<String>) context.deserialize(jo.get("costMatrix"), CostMatrix.class) : null);
return ret;
}
}
public static class Serializer<T> implements JsonSerializer<InMemoryData<T>> {
@Override
public JsonElement serialize(InMemoryData<T> data, Type type, JsonSerializationContext jsonSerializationContext) {
JsonObject je = new JsonObject();
je.add("objects", jsonSerializationContext.serialize(data.getObjects(), new TypeToken<Collection<LObject<T>>>(){}.getType()));
je.add("assigns", jsonSerializationContext.serialize(data.getAssigns(), new TypeToken<Collection<AssignedLabel<T>>>(){}.getType()));
return je;
}
}
public static class NominalSerializer implements JsonSerializer<InMemoryNominalData>{
@Override
public JsonElement serialize(InMemoryNominalData data, Type type, JsonSerializationContext jsonSerializationContext) {
Serializer<String> serializer = new Serializer<String>();
JsonObject ret = serializer.serialize(data, type, jsonSerializationContext).getAsJsonObject();
ret.addProperty("fixedPriors", data.arePriorsFixed());
ret.add("categories", jsonSerializationContext.serialize(data.getCategories()));
if (data.getCategoryPriors() != null){
JsonArray categoryPriors = new JsonArray();
for (Map.Entry<String, Double> e: data.getCategoryPriors().entrySet()){
categoryPriors.add(jsonSerializationContext.serialize(new CategoryValue(e.getKey(), e.getValue())));
}
ret.add("categoryPriors", categoryPriors);
}
ret.add("costMatrix", jsonSerializationContext.serialize(data.getCostMatrix()));
return ret;
}
}
public static class AssignSerializer<T> implements JsonSerializer<AssignedLabel<T>> {
@Override
public JsonElement serialize(AssignedLabel<T> tAssignedLabel, Type type, JsonSerializationContext jsonSerializationContext) {
return jsonSerializationContext.serialize(new ShallowAssign<T>(tAssignedLabel));
}
}
public static class AssignDeserializer<T> implements JsonDeserializer<AssignedLabel<T>> {
private Type type;
public AssignDeserializer(Type type){
this.type = type;
}
@Override
public AssignedLabel<T> deserialize(JsonElement element, Type type, JsonDeserializationContext context) throws JsonParseException {
ShallowAssign<T> sassign = context.deserialize(element, this.type);
return new AssignedLabel<T>(
new Worker(sassign.worker),
new LObject<T>(sassign.object),
sassign.label);
}
}
public static class WorkerSerializer implements JsonSerializer<Worker> {
@Override
public JsonElement serialize(Worker w, Type type, JsonSerializationContext ctx) {
return new JsonPrimitive(w.getName());
}
}
public static class WorkerDeserializer<T> implements JsonDeserializer<Worker> {
@Override
public Worker deserialize(JsonElement element, Type type, JsonDeserializationContext context) throws JsonParseException {
return new Worker(element.getAsString());
}
}
public static class CostMatrixSerializer<T> implements JsonSerializer<CostMatrix<T>> {
@Override
public JsonElement serialize(CostMatrix<T> w, Type type, JsonSerializationContext ctx) {
JsonArray ja = new JsonArray();
for (T from : w.getKnownValues()){
for(T to: w.getKnownValues())
ja.add(ctx.serialize(new MatrixValue(from, to, w.getCost(from, to))));
}
return ja;
}
}
public static class CostMatrixDeserializer<T> implements JsonDeserializer<CostMatrix<T>> {
@Override
public CostMatrix<T> deserialize(JsonElement element, Type type, JsonDeserializationContext context) throws JsonParseException {
CostMatrix<T> cm = new CostMatrix<T>();
for (JsonElement je : element.getAsJsonArray()){
MatrixValue<T> mv = context.deserialize(je, MatrixValue.class);
cm.add(mv.from, mv.to, mv.value);
}
return cm;
}
}
public static class DatumCreatorDeserializer<T> implements JsonDeserializer<ResultsFactory.DatumResultCreator<T>> {
@Override
public ResultsFactory.DatumResultCreator<T> deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
JsonObject jo = jsonElement.getAsJsonObject();
ResultsFactory.DatumResultFactoryCreator creator = new ResultsFactory.DatumResultFactoryCreator();
return creator.create(jo.get("clazz").getAsString());
}
}
public static class WorkerCreatorDeserializer<T> implements JsonDeserializer<ResultsFactory.WorkerResultCreator<T>> {
@Override
public ResultsFactory.WorkerResultCreator<T> deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
JsonObject jo = jsonElement.getAsJsonObject();
ResultsFactory.WorkerResultFactoryCreator creator = new ResultsFactory.WorkerResultFactoryCreator();
return creator.create(jo.get("clazz").getAsString());
}
}
public static class JsonObjectSerializer implements JsonSerializer<JsonObject> {
@Override
public JsonElement serialize(JsonObject jo, Type type, JsonSerializationContext ctx) {
return jo;
}
}
public static class JsonObjectDeserializer implements JsonDeserializer<JsonObject> {
@Override
public JsonObject deserialize(JsonElement jo, Type type, JsonDeserializationContext ctx) {
return jo.getAsJsonObject();
}
}
public static class GenericCollectionDeserializer<T> implements JsonDeserializer<Collection<T>> {
private String collectionName;
private Type type;
public GenericCollectionDeserializer(String collectionName, Type type){
this.collectionName = collectionName;
this.type = type;
}
@Override
public Collection<T> deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext context) throws JsonParseException {
Collection<T> ret = new ArrayList<T>();
JsonArray jArray;
if (jsonElement.isJsonArray()) {
jArray = jsonElement.getAsJsonArray();
} else {
jArray = jsonElement.getAsJsonObject().get(collectionName).getAsJsonArray();
}
for (JsonElement je : jArray){
ret.add((T)context.deserialize(je, this.type));
}
return ret;
}
}
}