package io.github.ibuildthecloud.gdapi.response; import io.github.ibuildthecloud.gdapi.context.ApiContext; import io.github.ibuildthecloud.gdapi.factory.SchemaFactory; import io.github.ibuildthecloud.gdapi.json.ActionLinksMapper; import io.github.ibuildthecloud.gdapi.json.JsonMapper; import io.github.ibuildthecloud.gdapi.model.Collection; import io.github.ibuildthecloud.gdapi.model.Resource; import io.github.ibuildthecloud.gdapi.model.Schema; import io.github.ibuildthecloud.gdapi.model.impl.CollectionImpl; import io.github.ibuildthecloud.gdapi.model.impl.WrappedResource; import io.github.ibuildthecloud.gdapi.request.ApiRequest; import io.github.ibuildthecloud.gdapi.request.handler.AbstractApiRequestHandler; import java.io.BufferedOutputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.List; public class JsonResponseWriter extends AbstractApiRequestHandler { JsonMapper jsonMapper; JsonMapper actionLinksMapper = new ActionLinksMapper(); boolean chunked = true; @Override public void handle(ApiRequest request) throws IOException { if (request.isCommitted()) return; if (!getResponseFormat().equals(request.getResponseFormat())) { return; } Object responseObject = getResponseObject(request); if (responseObject == null) return; request.setResponseContentType(getContentType()); JsonMapper jsonMapper = this.jsonMapper; if (request.getServletContext().getRequest().getHeader("X-API-Action-Links") != null) { jsonMapper = actionLinksMapper; } OutputStream os = request.getOutputStream(); BufferedOutputStream buf = new BufferedOutputStream(os); ByteArrayOutputStream baos = new ByteArrayOutputStream(); writeJson(jsonMapper, chunked ? buf : baos, responseObject, request); buf.flush(); if (!chunked) { byte[] bytes = baos.toByteArray(); request.getServletContext().getResponse().setContentLength(bytes.length); os.write(bytes); os.flush(); } } protected String getContentType() { return "application/json; charset=utf-8"; } protected String getResponseFormat() { return "json"; } protected Object getResponseObject(ApiRequest request) { Object object = request.getResponseObject(); if (object instanceof List) { return createCollection((List<?>)object, request); } else if (object instanceof Collection) { return object; } return createResource(request.getSchemaFactory(), object); } protected Collection createCollection(List<?> list, ApiRequest request) { CollectionImpl collection = new CollectionImpl(); collection.setResourceType(request.getType()); for (Object obj : list) { Resource resource = createResource(request.getSchemaFactory(), obj); if (resource != null) { collection.getData().add(resource); if (collection.getResourceType() == null) { collection.setResourceType(resource.getType()); } } } return collection; } protected Resource createResource(SchemaFactory schemaFactory, Object obj) { if (obj == null) return null; if (obj instanceof Resource) return (Resource)obj; Schema schema = schemaFactory.getSchema(obj.getClass()); ApiContext apiContext = ApiContext.getContext(); return schema == null ? null : new WrappedResource(apiContext.getIdFormatter(), schemaFactory, schema, obj, apiContext.getApiRequest().getMethod()); } protected void writeJson(JsonMapper jsonMapper, OutputStream os, Object responseObject, ApiRequest request) throws IOException { jsonMapper.writeValue(os, responseObject); } public JsonMapper getJsonMapper() { return jsonMapper; } public void setJsonMapper(JsonMapper jsonMapper) { this.jsonMapper = jsonMapper; } public boolean isChunked() { return chunked; } public void setChunked(boolean chunked) { this.chunked = chunked; } }