com.docdoku.server.rest.InstanceMessageBodyWriter.java Source code

Java tutorial

Introduction

Here is the source code for com.docdoku.server.rest.InstanceMessageBodyWriter.java

Source

/*
 * DocDoku, Professional Open Source
 * Copyright 2006 - 2013 DocDoku SARL
 *
 * This file is part of DocDokuPLM.
 *
 * DocDokuPLM is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * DocDokuPLM 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with DocDokuPLM.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.docdoku.server.rest;

import com.docdoku.core.meta.InstanceAttribute;
import com.docdoku.core.product.CADInstance;
import com.docdoku.core.product.Geometry;
import com.docdoku.core.product.PartIteration;
import com.docdoku.core.product.PartMaster;
import com.docdoku.core.product.PartRevision;
import com.docdoku.core.product.PartUsageLink;
import com.docdoku.server.rest.dto.GeometryDTO;
import com.docdoku.server.rest.dto.InstanceAttributeDTO;
import com.docdoku.server.rest.dto.InstanceDTO;
import com.sun.jersey.api.json.JSONJAXBContext;
import com.sun.jersey.api.json.JSONMarshaller;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
import javax.ws.rs.ext.Providers;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import org.apache.commons.lang.StringUtils;
import org.dozer.DozerBeanMapperSingletonWrapper;
import org.dozer.Mapper;

/**
 *
 * @author Florent Garin
 */
@Provider
@Produces("application/json;charset=UTF-8")
public class InstanceMessageBodyWriter implements MessageBodyWriter<InstanceCollection> {

    private static final String CHARSET = "charset";

    private Mapper mapper = DozerBeanMapperSingletonWrapper.getInstance();

    private ThreadLocal<byte[]> tlComma = new ThreadLocal<byte[]>();
    private ThreadLocal<Boolean> tlAddComma = new ThreadLocal<Boolean>();

    private ThreadLocal<JSONMarshaller> tlMarshaller = new ThreadLocal<JSONMarshaller>();
    private ThreadLocal<OutputStream> tlEntityStream = new ThreadLocal<OutputStream>();

    @Context
    protected Providers providers;

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

    @Override
    public long getSize(InstanceCollection t, Class<?> type, Type genericType, Annotation[] annotations,
            MediaType mediaType) {
        return -1;
    }

    @Override
    public void writeTo(InstanceCollection object, Class<?> type, Type genericType, Annotation[] annotations,
            MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
            throws IOException, WebApplicationException {
        try {
            //Class<?> domainClass = getDomainClass(genericType);
            setEntityStream(entityStream);
            setMarshaller(((JSONJAXBContext) getJAXBContext(InstanceDTO.class, mediaType)).createJSONMarshaller());
            Map<String, String> mediaTypeParameters = mediaType.getParameters();
            String charSet = "UTF-8";
            if (mediaTypeParameters.containsKey(CHARSET)) {
                charSet = mediaTypeParameters.get(CHARSET);
                getMarshaller().setProperty(Marshaller.JAXB_ENCODING, charSet);
            }

            PartUsageLink rootUsageLink = object.getRootUsageLink();
            List<Integer> usageLinkPaths = object.getUsageLinkPaths();
            byte[] leftSquareBrace = "[".getBytes(charSet);
            byte[] rightSquareBrace = "]".getBytes(charSet);
            setComma(",".getBytes(charSet));

            setAddComma(false);
            getEntityStream().write(leftSquareBrace);
            generateInstanceStream(rootUsageLink, 0, 0, 0, 0, 0, 0, usageLinkPaths, new ArrayList<Integer>());
            getEntityStream().write(rightSquareBrace);
        } catch (JAXBException ex) {
            throw new WebApplicationException(ex);
        } finally {
            tlEntityStream.remove();
            tlMarshaller.remove();
            tlAddComma.remove();
            tlComma.remove();
        }

    }

    private JAXBContext getJAXBContext(Class<?> type, MediaType mediaType) throws JAXBException {
        ContextResolver<JAXBContext> resolver = providers.getContextResolver(JAXBContext.class, mediaType);
        JAXBContext jaxbContext;
        if (resolver == null || (jaxbContext = resolver.getContext(type)) == null) {
            return JAXBContext.newInstance(type);
        } else {
            return jaxbContext;
        }
    }

    private void generateInstanceStream(PartUsageLink usageLink, double tx, double ty, double tz, double rx,
            double ry, double rz, List<Integer> filteredPath, List<Integer> instanceIds)
            throws JAXBException, IOException {

        //List<InstanceDTO> instancesDTO = new ArrayList<InstanceDTO>();

        PartMaster pm = usageLink.getComponent();
        PartRevision partR = pm.getLastRevision();
        PartIteration partI = partR.getLastIteration();

        String partIterationId = new StringBuilder().append(pm.getNumber()).append("-").append(partR.getVersion())
                .append("-").append(partI.getIteration()).toString();

        List<GeometryDTO> files = new ArrayList<GeometryDTO>();
        List<InstanceAttributeDTO> attributes = new ArrayList<InstanceAttributeDTO>();

        for (Geometry geometry : partI.getGeometries()) {
            files.add(mapper.map(geometry, GeometryDTO.class));
        }

        for (InstanceAttribute attr : partI.getInstanceAttributes().values()) {
            attributes.add(mapper.map(attr, InstanceAttributeDTO.class));
        }

        for (CADInstance instance : usageLink.getCadInstances()) {

            //compute absolutes values
            double atx = tx + getRelativeTxAfterParentRotation(rx, ry, rz, instance.getTx(), instance.getTy(),
                    instance.getTz());
            double aty = ty + getRelativeTyAfterParentRotation(rx, ry, rz, instance.getTx(), instance.getTy(),
                    instance.getTz());
            double atz = tz + getRelativeTzAfterParentRotation(rx, ry, rz, instance.getTx(), instance.getTy(),
                    instance.getTz());
            double arx = rx + instance.getRx();
            double ary = ry + instance.getRy();
            double arz = rz + instance.getRz();
            instanceIds.add(instance.getId());
            String id = StringUtils.join(instanceIds.toArray(), "-");

            if (!partI.isAssembly() && partI.getGeometries().size() > 0 && filteredPath.isEmpty()) {
                if (getAddComma())
                    getEntityStream().write(getComma());

                getMarshaller().marshallToJSON(
                        new InstanceDTO(id, partIterationId, atx, aty, atz, arx, ary, arz, files, attributes),
                        getEntityStream());
                setAddComma(true);
            } else {
                for (PartUsageLink component : partI.getComponents()) {
                    ArrayList<Integer> copyInstanceIds = new ArrayList<Integer>(instanceIds);
                    if (filteredPath.isEmpty()) {
                        generateInstanceStream(component, atx, aty, atz, arx, ary, arz, filteredPath,
                                copyInstanceIds);
                    } else if (component.getId() == filteredPath.get(0)) {
                        ArrayList<Integer> copyWithoutCurrentId = new ArrayList<Integer>(filteredPath);
                        copyWithoutCurrentId.remove(0);
                        generateInstanceStream(component, atx, aty, atz, arx, ary, arz, copyWithoutCurrentId,
                                copyInstanceIds);
                    }
                }
            }
        }
    }

    private double getRelativeTxAfterParentRotation(double rx, double ry, double rz, double tx, double ty,
            double tz) {

        double a = Math.cos(ry) * Math.cos(rz);
        double b = -Math.cos(rx) * Math.sin(rz) + Math.sin(rx) * Math.sin(ry) * Math.cos(rz);
        double c = Math.sin(rx) * Math.sin(rz) + Math.cos(rx) * Math.sin(ry) * Math.cos(rz);

        return a * tx + b * ty + c * tz;
    }

    private double getRelativeTyAfterParentRotation(double rx, double ry, double rz, double tx, double ty,
            double tz) {

        double d = Math.cos(ry) * Math.sin(rz);
        double e = Math.cos(rx) * Math.cos(rz) + Math.sin(rx) * Math.sin(ry) * Math.sin(rz);
        double f = -Math.sin(rx) * Math.cos(rz) + Math.cos(rx) * Math.sin(ry) * Math.sin(rz);

        return d * tx + e * ty + f * tz;
    }

    private double getRelativeTzAfterParentRotation(double rx, double ry, double rz, double tx, double ty,
            double tz) {

        double g = -Math.sin(ry);
        double h = Math.sin(rx) * Math.cos(ry);
        double i = Math.cos(rx) * Math.cos(ry);

        return g * tx + h * ty + i * tz;
    }

    private Class<?> getDomainClass(Type genericType) {
        if (genericType instanceof Class) {
            return (Class<?>) genericType;
        } else if (genericType instanceof ParameterizedType) {
            return (Class<?>) ((ParameterizedType) genericType).getActualTypeArguments()[0];
        } else {
            return null;
        }
    }

    private byte[] getComma() {
        return tlComma.get();
    }

    private void setComma(byte[] c) {
        tlComma.set(c);
    }

    private boolean getAddComma() {
        return tlAddComma.get();
    }

    private void setAddComma(boolean b) {
        tlAddComma.set(b);
    }

    private OutputStream getEntityStream() {
        return tlEntityStream.get();
    }

    private void setEntityStream(OutputStream out) {
        tlEntityStream.set(out);
    }

    private JSONMarshaller getMarshaller() {
        return tlMarshaller.get();
    }

    private void setMarshaller(JSONMarshaller m) {
        tlMarshaller.set(m);
    }

}