001/*
002 * Copyright (c) 2006-2012 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the Eclipse Public License v1.0
006 * which accompanies this distribution, and is available at
007 * http://www.eclipse.org/legal/epl-v10.html
008 *
009 * Contributors:
010 *     Nuxeo
011 */
012
013package org.nuxeo.ecm.automation.jaxrs.io;
014
015import java.io.IOException;
016import java.io.OutputStream;
017import java.io.Serializable;
018import java.lang.annotation.Annotation;
019import java.lang.reflect.Type;
020import java.util.Map;
021
022import javax.ws.rs.Produces;
023import javax.ws.rs.WebApplicationException;
024import javax.ws.rs.core.Context;
025import javax.ws.rs.core.MediaType;
026import javax.ws.rs.core.MultivaluedMap;
027import javax.ws.rs.ext.MessageBodyWriter;
028import javax.ws.rs.ext.Provider;
029
030import org.apache.commons.logging.Log;
031import org.apache.commons.logging.LogFactory;
032import org.codehaus.jackson.JsonEncoding;
033import org.codehaus.jackson.JsonFactory;
034import org.codehaus.jackson.JsonGenerator;
035import org.nuxeo.ecm.automation.core.util.PaginableRecordSet;
036import org.nuxeo.ecm.automation.core.util.RecordSet;
037
038/**
039 * Manage JSON Marshalling for {@link RecordSet} objects
040 *
041 * @author <a href="mailto:tdelprat@nuxeo.com">Tiry</a>
042 * @since 5.7
043 */
044@Provider
045@Produces({ "application/json+nxentity", "application/json" })
046public class JsonRecordSetWriter implements MessageBodyWriter<RecordSet> {
047
048    protected static Log log = LogFactory.getLog(JsonRecordSetWriter.class);
049
050    @Context
051    JsonFactory factory;
052
053    @Override
054    public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
055        boolean canUse = RecordSet.class.isAssignableFrom(type);
056        return canUse;
057    }
058
059    @Override
060    public long getSize(RecordSet t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
061        return -1L;
062    }
063
064    @Override
065    public void writeTo(RecordSet records, Class<?> type, Type genericType, Annotation[] annotations,
066            MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream out) throws IOException,
067            WebApplicationException {
068        try {
069            writeRecords(out, records);
070        } catch (IOException e) {
071            log.error("Failed to serialize recordset", e);
072            throw new WebApplicationException(500);
073        }
074
075    }
076
077    protected void writeRecords(OutputStream out, RecordSet records) throws IOException {
078
079        JsonGenerator jg = factory.createJsonGenerator(out, JsonEncoding.UTF8);
080
081        jg.writeStartObject();
082        jg.writeStringField("entity-type", "recordSet");
083
084        if (records instanceof PaginableRecordSet) {
085            PaginableRecordSet pRecord = (PaginableRecordSet) records;
086            jg.writeBooleanField("isPaginable", true);
087            jg.writeNumberField("resultsCount", pRecord.getResultsCount());
088            jg.writeNumberField("pageSize", pRecord.getPageSize());
089            jg.writeNumberField("maxPageSize", pRecord.getMaxPageSize());
090            jg.writeNumberField("currentPageSize", pRecord.getCurrentPageSize());
091            jg.writeNumberField("currentPageIndex", pRecord.getCurrentPageIndex());
092            jg.writeNumberField("numberOfPages", pRecord.getNumberOfPages());
093            jg.writeBooleanField("isPreviousPageAvailable", pRecord.isPreviousPageAvailable());
094            jg.writeBooleanField("isNextPageAvailable", pRecord.isNextPageAvailable());
095            jg.writeBooleanField("isLastPageAvailable", pRecord.isLastPageAvailable());
096            jg.writeBooleanField("isSortable", pRecord.isSortable());
097            jg.writeBooleanField("hasError", pRecord.hasError());
098            jg.writeStringField("errorMessage", pRecord.getErrorMessage());
099        }
100
101        jg.writeArrayFieldStart("entries");
102        for (Map<String, Serializable> entry : records) {
103            jg.writeObject(entry);
104        }
105
106        if (records instanceof PaginableRecordSet) {
107            PaginableRecordSet pRecord = (PaginableRecordSet) records;
108            if (pRecord.hasAggregateSupport() && pRecord.getAggregates() != null && !pRecord.getAggregates().isEmpty()) {
109                jg.writeObjectField("aggregations", pRecord.getAggregates());
110            }
111        }
112
113        jg.writeEndArray();
114        jg.writeEndObject();
115        jg.flush();
116    }
117
118}