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 com.fasterxml.jackson.core.JsonEncoding;
034import com.fasterxml.jackson.core.JsonFactory;
035import com.fasterxml.jackson.core.JsonGenerator;
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)
069            throws IOException, WebApplicationException {
070
071        writeEntity(factory.createJsonGenerator(entityStream, JsonEncoding.UTF8), entity);
072    }
073
074    public void writeEntity(JsonGenerator jg, T item) throws IOException {
075        jg.writeStartObject();
076        jg.writeStringField("entity-type", getEntityType());
077
078        writeEntityBody(jg, item);
079        jg.writeEndObject();
080        jg.flush();
081
082    }
083
084    /**
085     * Write the body of the entity. The object has already been opened and it entity-type rendered.
086     */
087    abstract protected void writeEntityBody(JsonGenerator jg, T item) throws IOException;
088
089    /**
090     * get the Entity type of the current entity type. It MUST follow camelCase notation
091     *
092     * @return the string representing the entity-type.
093     */
094    abstract protected String getEntityType();
095
096}