package cz.cvut.fel.adaptiverestfulapi.serialization.application.json;
import com.google.gson.*;
import cz.cvut.fel.adaptiverestfulapi.meta.configuration.Configuration;
import cz.cvut.fel.adaptiverestfulapi.meta.model.Attribute;
import cz.cvut.fel.adaptiverestfulapi.meta.model.Entity;
import cz.cvut.fel.adaptiverestfulapi.meta.model.Model;
import cz.cvut.fel.adaptiverestfulapi.meta.model.Relationship;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
public class EntityDeserializer implements JsonDeserializer {
private Entity entity;
private Model model;
private Configuration configuration;
public EntityDeserializer(Entity entity, Model model, Configuration configuration) {
this.entity = entity;
this.model = model;
this.configuration = configuration;
}
@Override
public Object deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext context) throws JsonParseException {
Object object = this.createInstance();
if (!jsonElement.isJsonObject()) {
throw new JsonParseException("JSON element for " + this.entity.getName() + " is not a JSON object");
}
this.deserializeAttributes(object, (JsonObject)jsonElement, type, context);
this.deserializeRelationships(object, (JsonObject)jsonElement, type, context);
return object;
}
protected Object createInstance() throws JsonParseException {
return this.createInstance(this.entity);
}
protected Object createInstance(Entity entity) throws JsonParseException {
try {
return entity.getEntityClass().newInstance();
} catch (InstantiationException e) {
throw new JsonParseException(e);
} catch (IllegalAccessException e) {
throw new JsonParseException(e);
}
}
protected void deserializeAttributes(Object object, JsonObject jsonObject, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
for (Attribute attribute : this.entity.getAttributes().values()) {
if (attribute.getSetter() != null && jsonObject.has(attribute.getShortName())) {
JsonElement element = jsonObject.get(attribute.getShortName());
this.deserializeAttribute(attribute, object, element, type, jsonDeserializationContext);
}
}
}
protected void deserializeAttribute(Attribute attribute, Object object, JsonElement jsonElement, Type type, JsonDeserializationContext context) throws JsonParseException {
Method setter = attribute.getSetter();
try {
Object value = context.deserialize(jsonElement, attribute.getAttributeType());
setter.invoke(object, value);
} catch (IllegalAccessException e) {
throw new JsonParseException(e);
} catch (InvocationTargetException e) {
throw new JsonParseException(e);
}
}
protected void deserializeRelationships(Object object, JsonObject jsonObject, Type type, JsonDeserializationContext context) throws JsonParseException {
JsonElement element = null;
for (Relationship relationship : this.entity.getRelationships().values()) {
if (relationship.getSetter() != null && jsonObject.has(relationship.getShortName())) {
element = jsonObject.get(relationship.getShortName());
if (relationship.isToOne()) {
if (element != null) {
this.deserializeToOne(relationship, object, element, type, context);
}
} else if (relationship.isToMany()) {
if (element == null) {
element = new JsonArray();
}
if (element.isJsonArray()) {
this.deserializeToMany(relationship, object, (JsonArray)element, type, context);
}
}
}
}
}
protected void deserializeToOne(Relationship relationship, Object object, JsonElement jsonElement, Type type, JsonDeserializationContext context) throws JsonParseException {
Method setter = relationship.getSetter();
try {
Entity targetEntity = this.model.entityForName(relationship.getTargetEntity());
Object targetObject = this.createInstance(targetEntity);
Attribute primary = targetEntity.getPrimary();
Object identifier = context.deserialize(jsonElement, primary.getAttributeType());
primary.getSetter().invoke(targetObject, identifier);
setter.invoke(object, targetObject);
} catch (IllegalAccessException e) {
throw new JsonParseException(e);
} catch (InvocationTargetException e) {
throw new JsonParseException(e);
}
}
protected void deserializeToMany(Relationship relationship, Object object, JsonArray jsonArray, Type type, JsonDeserializationContext context) throws JsonParseException {
// TODO think, think, think
}
}