package org.uncertweb.ps.handler.json.gson; import java.io.IOException; import java.lang.reflect.Type; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.Map.Entry; import org.uncertweb.ps.data.DataDescription; import org.uncertweb.ps.data.DataReference; import org.uncertweb.ps.data.MultipleInput; import org.uncertweb.ps.data.Request; import org.uncertweb.ps.data.RequestedOutput; import org.uncertweb.ps.data.SingleInput; import org.uncertweb.ps.encoding.EncodingRepository; import org.uncertweb.ps.encoding.ParseException; import org.uncertweb.ps.encoding.json.AbstractJSONEncoding; import org.uncertweb.ps.handler.data.DataReferenceParser; import org.uncertweb.ps.process.AbstractProcess; import org.uncertweb.ps.process.ProcessRepository; import com.google.gson.JsonArray; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; public class RequestDeserializer implements JsonDeserializer<Request> { public Request deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { // get our object Entry<String, JsonElement> root = json.getAsJsonObject().entrySet().iterator().next(); JsonObject object = root.getValue().getAsJsonObject(); // get process identifier String processIdentifier = root.getKey().substring(0, root.getKey().length() - "Request".length()); // create request Request request = new Request(processIdentifier); // for each input in process get class AbstractProcess process = ProcessRepository.getInstance().getProcess(processIdentifier); // FIXME: could be null for (String inputIdentifier : process.getInputIdentifiers()) { // get description DataDescription inputDescription = process.getInputDataDescription(inputIdentifier); // get input from json if (object.has(inputIdentifier)) { JsonElement inputElement = object.get(inputIdentifier); // data could be array or single object ArrayList<Object> objects = new ArrayList<Object>(); // parse data try { if (inputElement.isJsonArray()) { try { JsonArray dataArray = inputElement.getAsJsonArray(); for (JsonElement dataElement : dataArray) { objects.add(parseDataElement(dataElement, inputDescription, context)); } } catch (Exception e) { objects.add(parseDataElement(inputElement, inputDescription, context)); } } else { objects.add(parseDataElement(inputElement, inputDescription, context)); } } catch (Exception e) { throw new JsonParseException(e); } // create appropriate input if (objects.size() > 0) { if (inputDescription.getMaxOccurs() > 1) { request.getInputs().add(new MultipleInput(inputIdentifier, objects)); } else { request.getInputs().add(new SingleInput(inputIdentifier, objects.get(0))); } } } } // check for requested outputs if (object.has("RequestedOutputs")) { List<RequestedOutput> reqOutputs = request.getRequestedOutputs(); JsonObject outputsObj = object.get("RequestedOutputs").getAsJsonObject(); for (Entry<String, JsonElement> entry : outputsObj.entrySet()) { String outputIdentifier = entry.getKey(); JsonObject outputObj = entry.getValue().getAsJsonObject(); boolean asReference = false; if (outputObj.has("asReference")) { asReference = outputObj.get("asReference").getAsBoolean(); } reqOutputs.add(new RequestedOutput(outputIdentifier, asReference)); } } else { request.setRequestedOutputs(null); } return request; } private Object parseDataElement(JsonElement dataElement, DataDescription dataDescription, JsonDeserializationContext context) throws ParseException, IOException { Class<?> type = dataDescription.getType(); if (dataElement.isJsonObject() && dataElement.getAsJsonObject().has("DataReference")) { JsonObject dataReference = dataElement.getAsJsonObject().get("DataReference").getAsJsonObject(); // TODO: exceptions required if href and mimeType not set, compression is optional boolean compression = false; if (dataReference.has("compressed")) { compression = dataReference.get("compressed").getAsBoolean(); } // create url from string URL dataURL = new URL(dataReference.get("href").getAsString()); // parse data reference String mimeType = null; if (dataReference.has("mimeType")) { mimeType = dataReference.get("mimeType").getAsString(); } DataReference ref = new DataReference(dataURL, mimeType, compression); DataReferenceParser parser = new DataReferenceParser(); return parser.parse(ref, type); } else { // look in the factory first AbstractJSONEncoding encoding = EncodingRepository.getInstance().getJSONEncoding(type); if (encoding != null) { // convert to string and parse String json = dataElement.toString(); return encoding.parse(json, type); } else { // try and parse with gson try { return context.deserialize(dataElement, type); } catch (JsonParseException e) { throw new ParseException("Couldn't automatically parse " + type.getSimpleName() + " type."); } } } } }