001/*
002 * (C) Copyright 2013 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     dmetzler
018 */
019package org.nuxeo.ecm.automation.jaxrs.io;
020
021import java.io.IOException;
022import java.io.OutputStream;
023import java.lang.annotation.Annotation;
024import java.lang.reflect.ParameterizedType;
025import java.lang.reflect.Type;
026
027import javax.ws.rs.WebApplicationException;
028import javax.ws.rs.core.Context;
029import javax.ws.rs.core.MediaType;
030import javax.ws.rs.core.MultivaluedMap;
031import javax.ws.rs.ext.MessageBodyWriter;
032
033import org.codehaus.jackson.JsonEncoding;
034import org.codehaus.jackson.JsonFactory;
035import org.codehaus.jackson.JsonGenerator;
036import org.nuxeo.ecm.core.api.NuxeoException;
037import org.nuxeo.ecm.webengine.WebException;
038
039/**
040 * Base class to write json entities
041 *
042 * @since 5.7.3
043 */
044public abstract class EntityWriter<T> implements MessageBodyWriter<T> {
045
046    @Context
047    protected JsonFactory factory;
048
049    @SuppressWarnings({ "rawtypes", "unchecked" })
050    @Override
051    public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
052        if (genericType instanceof ParameterizedType) {
053            // See EntityListWriter to write Writer of parametrized class
054            return false;
055        } else {
056            ParameterizedType ptype = (ParameterizedType) this.getClass().getGenericSuperclass();
057            Type[] ts = ptype.getActualTypeArguments();
058            Class c = (Class) ts[0];
059            return c.isAssignableFrom(type);
060        }
061    }
062
063    @Override
064    public long getSize(T t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
065        return -1;
066    }
067
068    @Override
069    public void writeTo(T entity, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType,
070            MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException,
071            WebApplicationException {
072
073        try {
074            writeEntity(factory.createJsonGenerator(entityStream, JsonEncoding.UTF8), entity);
075        } catch (NuxeoException e) {
076            throw WebException.wrap(e);
077        }
078    }
079
080    public void writeEntity(JsonGenerator jg, T item) throws IOException {
081        jg.writeStartObject();
082        jg.writeStringField("entity-type", getEntityType());
083
084        writeEntityBody(jg, item);
085        jg.writeEndObject();
086        jg.flush();
087
088    }
089
090    /**
091     * Write the body of the entity. The object has already been opened and it entity-type rendered.
092     */
093    abstract protected void writeEntityBody(JsonGenerator jg, T item) throws IOException;
094
095    /**
096     * get the Entity type of the current entity type. It MUST follow camelCase notation
097     *
098     * @return the string representing the entity-type.
099     */
100    abstract protected String getEntityType();
101
102}