package org.uncertweb.ps.handler.json; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.util.ArrayList; import java.util.List; import org.uncertweb.ps.data.DataReference; import org.uncertweb.ps.data.Output; import org.uncertweb.ps.data.RequestedOutput; import org.uncertweb.ps.data.Response; import org.uncertweb.ps.encoding.EncodeException; import org.uncertweb.ps.encoding.json.AbstractJSONEncoding; import org.uncertweb.ps.handler.ResponseGenerateException; import org.uncertweb.ps.handler.data.DataReferenceGenerator; import org.uncertweb.ps.handler.json.gson.GsonWrapper; import org.uncertweb.ps.storage.StorageException; import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; public class JSONResponseGenerator { public static void generate(Response response, OutputStream outputStream) throws ResponseGenerateException { generate(response, null, outputStream); } public static void generate(Response response, List<RequestedOutput> reqOutputs, OutputStream outputStream) throws ResponseGenerateException { // build using gson Gson gson = GsonWrapper.getGson(); JsonObject responseObject = gson.toJsonTree(response).getAsJsonObject(); JsonObject innerObject = responseObject.get(response.getProcessIdentifier() + "Response").getAsJsonObject(); // check requested outputs if (reqOutputs != null) { // remove outputs not in requested, modify to references where necessary // FIXME: horribly inefficient for (Output output : response.getOutputs()) { String outputIdentifier = output.getIdentifier(); boolean include = false; boolean reference = false; // set include/reference flags for (RequestedOutput reqOutput : reqOutputs) { if (reqOutput.getName().equals(output.getIdentifier())) { include = true; reference = reqOutput.isReference(); break; } } // check include/reference flags if (!include) { // remove if not included innerObject.remove(outputIdentifier); } else { // convert to data reference if (reference) { try { JsonElement element = createReferenceElement(output); innerObject.add(outputIdentifier, element); } catch (EncodeException | StorageException e) { throw new ResponseGenerateException("Couldn't generate output data reference", e); } } } } } // write try { Writer writer = new OutputStreamWriter(outputStream); gson.toJson(responseObject, writer); writer.flush(); } catch (IOException e) { throw new ResponseGenerateException("Could not write response to stream", e); } } private static JsonElement createReferenceElement(Output output) throws EncodeException, StorageException { // objects to encode List<Object> objects; if (output.isSingleOutput()) { objects = new ArrayList<Object>(); objects.add(output.getAsSingleOutput().getObject()); } else { objects = output.getAsMultipleOutput().getObjects(); } // generate references DataReferenceGenerator gen = new DataReferenceGenerator(); List<JsonObject> refObjs = new ArrayList<JsonObject>(); for (Object obj : objects) { DataReference ref = gen.generate(obj, AbstractJSONEncoding.class); JsonObject refObj = new JsonObject(); refObj.addProperty("href", ref.getURL().toString()); refObj.addProperty("mimeType", ref.getMimeType()); JsonObject outerRefObj = new JsonObject(); outerRefObj.add("DataReference", refObj); refObjs.add(outerRefObj); } // add to response object JsonElement element; if (output.isSingleOutput()) { element = refObjs.get(0); } else { element = new JsonArray(); for (JsonObject refObj : refObjs) { ((JsonArray)element).add(refObj); } } return element; } }