package cz.cvut.fel.adaptiverestfulapi.serialization.application.json; import com.google.gson.*; import com.google.gson.JsonSerializer; import cz.cvut.fel.adaptiverestfulapi.core.HttpContext; 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 cz.cvut.fel.adaptiverestfulapi.serialization.Authorization; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.util.Collection; public class EntitySerializer implements JsonSerializer { private Entity entity; private Model model; private Configuration configuration; private HttpContext httpContext; public EntitySerializer(Entity entity, Model model, Configuration configuration) { this.entity = entity; this.model = model; this.configuration = configuration; } public void setHttpContext(HttpContext httpContext) { this.httpContext = httpContext; } @Override public JsonElement serialize(Object object, Type typeOfSrc, JsonSerializationContext context) throws JsonParseException { Authorization auth = this.configuration.get(Authorization.Key, this.entity); if (auth != null && !auth.isAllowed(this.httpContext)) { return null; } JsonObject jsonObject = new JsonObject(); this.serializeAttributes(object, typeOfSrc, jsonObject, context); this.serializeRelationships(object, typeOfSrc, jsonObject, context); return jsonObject; } protected void serializeAttributes(Object object, Type typeOfSrc, JsonObject jsonObject, JsonSerializationContext context) throws JsonParseException { for (Attribute attribute : this.entity.getAttributes().values()) { Authorization auth = this.configuration.get(Authorization.Key, attribute); if (auth != null && !auth.isAllowed(this.httpContext)) { continue; } if (attribute.getGetter() != null) { this.serializeAttribute(attribute, object, typeOfSrc, jsonObject, context); } } } protected void serializeAttribute(Attribute attribute, Object object, Type typeOfSrc, JsonObject jsonObject, JsonSerializationContext context) throws JsonParseException { Method getter = attribute.getGetter(); String name = attribute.getShortName(); try { Object value = getter.invoke(object); jsonObject.add(name, context.serialize(value)); } catch (IllegalAccessException e) { throw new JsonParseException(e); } catch (InvocationTargetException e) { throw new JsonParseException(e); } } protected void serializeRelationships(Object object, Type typeOfSrc, JsonObject jsonObject, JsonSerializationContext context) throws JsonParseException { for (Relationship relationship : this.entity.getRelationships().values()) { Authorization auth = this.configuration.get(Authorization.Key, relationship); if (auth != null && !auth.isAllowed(this.httpContext)) { continue; } if (relationship.getGetter() != null) { if (relationship.isToOne()) { this.serializeToOne(relationship, object, typeOfSrc, jsonObject, context); } else if (relationship.isToMany()) { this.serializeToMany(relationship, object, typeOfSrc, jsonObject, context); } } } } /** * Serializes `toOne` relationship with identifier, eq: "project": 3. * @param relationship * @param object * @param typeOfSrc * @param jsonObject * @param context * @throws JsonParseException */ protected void serializeToOne(Relationship relationship, Object object, Type typeOfSrc, JsonObject jsonObject, JsonSerializationContext context) throws JsonParseException { Method getter = relationship.getGetter(); String name = relationship.getShortName(); try { Object target = getter.invoke(object); if (target != null) { getter = this.model.entityForName(relationship.getTargetEntity()).getPrimary().getGetter(); Object id = getter.invoke(target); jsonObject.add(name, context.serialize(id)); } else { jsonObject.add(name, context.serialize(null)); } } catch (IllegalAccessException e) { throw new JsonParseException(e); } catch (InvocationTargetException e) { throw new JsonParseException(e); } } /** * Serializes `toMany` relationship as an array of IDs, eq: "issues": [1, 2, 3]. * @param relationship * @param object * @param typeOfSrc * @param jsonObject * @param context * @throws JsonParseException */ protected void serializeToMany(Relationship relationship, Object object, Type typeOfSrc, JsonObject jsonObject, JsonSerializationContext context) throws JsonParseException { Method getter = relationship.getGetter(); String name = relationship.getShortName(); try { Collection collection = (Collection)getter.invoke(object); getter = this.model.entityForName(relationship.getTargetEntity()).getPrimary().getGetter(); JsonArray ids = new JsonArray(); for (Object obj : collection) { Object id = getter.invoke(obj); ids.add(context.serialize(id)); } jsonObject.add(name, ids); } catch (IllegalAccessException e) { throw new JsonParseException(e); } catch (InvocationTargetException e) { throw new JsonParseException(e); } } }