scott.barleyrs.rest.EntityResultMessageBodyWriter.java Source code

Java tutorial

Introduction

Here is the source code for scott.barleyrs.rest.EntityResultMessageBodyWriter.java

Source

package scott.barleyrs.rest;

/*
 * #%L
 * BarleyRS
 * $Id:$
 * $HeadURL:$
 * %%
 * Copyright (C) 2014 - 2016 Scott Sinclair
 *       <scottysinclair@gmail.com>
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * <http://www.gnu.org/licenses/lgpl-3.0.html>.
 * #L%
 */

import java.io.IOException;
import java.io.OutputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

import scott.barleydb.api.core.entity.Entity;
import scott.barleydb.api.core.entity.EntityContextState;
import scott.barleydb.api.core.entity.Node;
import scott.barleydb.api.core.entity.NotLoaded;
import scott.barleydb.api.core.entity.RefNode;
import scott.barleydb.api.core.entity.ToManyNode;
import scott.barleydb.api.core.entity.ValueNode;

@Provider
@Produces(MediaType.APPLICATION_JSON)
public class EntityResultMessageBodyWriter implements MessageBodyWriter<Entity> {

    private static final SimpleDateFormat df = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");

    private final List<String> namespaces;

    public EntityResultMessageBodyWriter() {
        System.out.println("IW NEW!!!");
        this.namespaces = new LinkedList<String>();
        namespaces.add("scott.picdb");
    }

    @Override
    public long getSize(Entity arg0, Class<?> arg1, Type arg2, Annotation[] arg3, MediaType arg4) {
        return 0; //not needed by jersey
    }

    @Override
    public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
        boolean result = (mediaType.equals(MediaType.APPLICATION_JSON_TYPE) && type.equals(Entity.class));
        return result;
    }

    @Override
    public void writeTo(Entity result, Class<?> type, Type genericType, Annotation[] annotations,
            MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
            throws IOException, WebApplicationException {
        System.out.println("converting Entity to JSON");
        result.getEntityContext().setEntityContextState(EntityContextState.INTERNAL);
        try {
            ObjectMapper mapper = new ObjectMapper();
            JsonGenerator gen = mapper.getFactory().createGenerator(entityStream);
            Set<Entity> started = new HashSet<>();
            JsonNode json = toJson(mapper, result, started);
            gen.writeTree(json);
        } finally {
            result.getEntityContext().setEntityContextState(EntityContextState.USER);
        }

    }

    private JsonNode toJson(ObjectMapper mapper, Entity entity, Set<Entity> started) {
        if (!started.add(entity)) {
            return null;
        }
        try {
            ObjectNode jsonEntity = mapper.createObjectNode();
            for (Node node : entity.getChildren(Node.class)) {
                putNode(mapper, jsonEntity, node, started);
            }
            return jsonEntity;
        } finally {
            started.remove(entity);
        }
    }

    private void putNode(ObjectMapper mapper, ObjectNode jsonEntity, Node node, Set<Entity> started) {
        if (node instanceof ValueNode) {
            setValue(jsonEntity, node.getName(), (ValueNode) node);
        } else if (node instanceof RefNode) {
            Entity reffedEntity = ((RefNode) node).getReference(false);
            if (reffedEntity != null) {
                if (reffedEntity.isLoadedOrNew()) {
                    JsonNode je = toJson(mapper, reffedEntity, started);
                    if (je != null) {
                        jsonEntity.set(node.getName(), je);
                    }
                } else if (reffedEntity.isFetchRequired()) {
                    /*
                     * a fetch is required, we just output the ID
                     */
                    jsonEntity.put(node.getName(), reffedEntity.getKey().getValue().toString());
                }

            } else {
                jsonEntity.putNull(node.getName());
            }
        } else if (node instanceof ToManyNode) {
            ToManyNode tm = (ToManyNode) node;
            if (!tm.getList().isEmpty()) {
                ArrayNode array = jsonEntity.arrayNode();
                for (Entity e : tm.getList()) {
                    JsonNode je = toJson(mapper, e, started);
                    if (je != null) {
                        array.add(je);
                    }
                }
                jsonEntity.set(tm.getName(), array);
            }
        }
    }

    private void setValue(ObjectNode jsonEntity, String name, ValueNode node) {
        Object value = node.getValue();
        if (value == null) {
            jsonEntity.putNull(node.getName());
        } else if (value instanceof String) {
            jsonEntity.put(node.getName(), (String) value);
        } else if (value instanceof Long) {
            jsonEntity.put(node.getName(), (Long) value);
        } else if (value instanceof Date) {
            jsonEntity.put(node.getName(), df.format((Date) value));
        } else if (value instanceof Integer) {
            jsonEntity.put(node.getName(), (Integer) value);
        } else if (value instanceof BigDecimal) {
            jsonEntity.put(node.getName(), (BigDecimal) value);
        } else if (value instanceof Boolean) {
            jsonEntity.put(node.getName(), (Boolean) value);
        } else if (value == NotLoaded.VALUE) {
            //we skip these properties
        } else {
            throw new IllegalStateException("Cannot serialize value of type " + value.getClass().getSimpleName());
        }
    }

}