001/*
002 * (C) Copyright 2013 Nuxeo SA (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl-2.1.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     dmetzler
016 */
017package org.nuxeo.ecm.automation.jaxrs.io;
018
019import java.io.IOException;
020import java.io.OutputStream;
021import java.lang.annotation.Annotation;
022import java.lang.reflect.ParameterizedType;
023import java.lang.reflect.Type;
024
025import javax.ws.rs.WebApplicationException;
026import javax.ws.rs.core.Context;
027import javax.ws.rs.core.MediaType;
028import javax.ws.rs.core.MultivaluedMap;
029import javax.ws.rs.ext.MessageBodyWriter;
030
031import org.codehaus.jackson.JsonEncoding;
032import org.codehaus.jackson.JsonFactory;
033import org.codehaus.jackson.JsonGenerator;
034import org.nuxeo.ecm.core.api.NuxeoException;
035import org.nuxeo.ecm.webengine.WebException;
036
037/**
038 * Base class to write json entities
039 *
040 * @since 5.7.3
041 */
042public abstract class EntityWriter<T> implements MessageBodyWriter<T> {
043
044    @Context
045    protected JsonFactory factory;
046
047    @SuppressWarnings({ "rawtypes", "unchecked" })
048    @Override
049    public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
050        if (genericType instanceof ParameterizedType) {
051            // See EntityListWriter to write Writer of parametrized class
052            return false;
053        } else {
054            ParameterizedType ptype = (ParameterizedType) this.getClass().getGenericSuperclass();
055            Type[] ts = ptype.getActualTypeArguments();
056            Class c = (Class) ts[0];
057            return c.isAssignableFrom(type);
058        }
059    }
060
061    @Override
062    public long getSize(T t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
063        return -1;
064    }
065
066    @Override
067    public void writeTo(T entity, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType,
068            MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException,
069            WebApplicationException {
070
071        try {
072            writeEntity(factory.createJsonGenerator(entityStream, JsonEncoding.UTF8), entity);
073        } catch (NuxeoException e) {
074            throw WebException.wrap(e);
075        }
076    }
077
078    public void writeEntity(JsonGenerator jg, T item) throws IOException {
079        jg.writeStartObject();
080        jg.writeStringField("entity-type", getEntityType());
081
082        writeEntityBody(jg, item);
083        jg.writeEndObject();
084        jg.flush();
085
086    }
087
088    /**
089     * Write the body of the entity. The object has already been opened and it entity-type rendered.
090     */
091    abstract protected void writeEntityBody(JsonGenerator jg, T item) throws IOException;
092
093    /**
094     * get the Entity type of the current entity type. It MUST follow camelCase notation
095     *
096     * @return the string representing the entity-type.
097     */
098    abstract protected String getEntityType();
099
100}