ispyb.server.common.services.shipping.Shipping3ServiceBean.java Source code

Java tutorial

Introduction

Here is the source code for ispyb.server.common.services.shipping.Shipping3ServiceBean.java

Source

/*************************************************************************************************
 * This file is part of ISPyB.
 * 
 * ISPyB 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.
 * 
 * ISPyB 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 Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with ISPyB.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * Contributors : S. Delageniere, R. Leal, L. Launer, K. Levik, S. Veyrier, P. Brenchereau, M. Bodin, A. De Maria Antolinos
 ****************************************************************************************************/
package ispyb.server.common.services.shipping;

import ispyb.server.biosaxs.services.sql.SqlTableMapper;

import ispyb.server.common.util.ejb.Ejb3ServiceLocator;
import ispyb.server.common.util.ejb.EJBAccessCallback;
import ispyb.server.common.util.ejb.EJBAccessTemplate;
import ispyb.server.common.vos.proposals.Proposal3VO;
import ispyb.server.common.vos.shipping.Container3VO;
import ispyb.server.common.vos.shipping.Dewar3VO;
import ispyb.server.common.vos.shipping.Shipping3VO;

import java.lang.reflect.Modifier;
import java.math.BigInteger;
import java.sql.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;
import javax.ejb.EJB;
import javax.ejb.SessionContext;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.FetchMode;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.hibernate.transform.AliasToEntityMapResultTransformer;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

/**
 * <p>
 * This session bean handles ISPyB Shipping3.
 * </p>
 */
@Stateless
public class Shipping3ServiceBean implements Shipping3Service, Shipping3ServiceLocal {

    private final static Logger LOG = Logger.getLogger(Shipping3ServiceBean.class);

    // Generic HQL request to find instances of Shipping3 by pk
    // TODO choose between left/inner join
    private static final String FIND_BY_PK(boolean fetchDewars) {
        return "from Shipping3VO vo " + (fetchDewars ? "left join fetch vo.dewarVOs " : "")
                + "where vo.shippingId = :pk";

    }

    private static final String FIND_BY_PK(boolean fetchDewars, boolean fetchSessions) {
        if (fetchDewars) {
            return "FROM Shipping3VO vo LEFT JOIN FETCH vo.dewarVOs dewars "
                    + (fetchSessions ? " LEFT JOIN FETCH dewars.sessionVO " : "") + " WHERE vo.shippingId = :pk";
        }
        return FIND_BY_PK(fetchDewars);
    }

    private static final String FIND_BY_PK(boolean fetchDewars, boolean fetchContainers, boolean fetchSamples) {
        if (fetchDewars) {
            return "FROM Shipping3VO vo LEFT JOIN FETCH vo.dewarVOs dewars "
                    + (fetchContainers ? " LEFT JOIN FETCH dewars.containerVOs co " : "")
                    + (fetchSamples ? " LEFT JOIN FETCH co.sampleVOs " : "") + " WHERE vo.shippingId = :pk";
        }
        return FIND_BY_PK(false);
    }

    private static final String FIND_BY_PK(boolean fetchDewars, boolean fetchContainers, boolean fetchSamples,
            boolean fetchSubSamples) {
        if (fetchDewars) {
            return "FROM Shipping3VO vo LEFT JOIN FETCH vo.dewarVOs dewars "
                    + (fetchContainers ? " LEFT JOIN FETCH dewars.containerVOs co " : "")
                    //+ (fetchSamples ? " LEFT JOIN FETCH co.sampleVOs sa " : "")
                    + (fetchSamples ? " LEFT JOIN FETCH co.sampleVOs sa LEFT JOIN FETCH sa.blsampleImageVOs " : "")
                    + (fetchSubSamples ? " LEFT JOIN FETCH sa.blSubSampleVOs " : "") + " WHERE vo.shippingId = :pk";
        }
        return FIND_BY_PK(fetchDewars);
    }

    private static final String FIND_BY_PROPOSAL_ID(boolean fetchDewars, boolean fetchContainers,
            boolean feacthSamples) {
        if (fetchDewars) {
            return "FROM Shipping3VO vo LEFT JOIN FETCH vo.dewarVOs dewars "
                    + (fetchContainers ? " LEFT JOIN FETCH dewars.containerVOs co " : "")
                    + (feacthSamples
                            ? " LEFT JOIN FETCH co.sampleVOs sa LEFT JOIN FETCH sa.blsampleImageVOs LEFT JOIN FETCH sa.blSubSampleVOs "
                            : " ")
                    + " LEFT JOIN FETCH vo.sessions se " + " LEFT JOIN FETCH se.proposalVO proposal "
                    + " WHERE proposal.proposalId = :proposalId";
        }
        return FIND_BY_PK(fetchDewars);
    }

    private static final String FIND_BY_SHIPPING_ID() {
        return "select  " + SqlTableMapper.getShippingTable()
                + ", (select count(*) from BLSample where BLSample.containerId = Container.containerId) as sampleCount, "
                + SqlTableMapper.getContainerTable()
                + " , (select count(*) from StockSolution where Dewar.dewarId = StockSolution.boxId) as stockSolutionCount, "
                + SqlTableMapper.getDewarTable() + " from Shipping \r\n"
                + " left join Dewar on Dewar.shippingId = Shipping.shippingId \r\n"
                + " left join Container on Dewar.dewarId = Container.dewarId \r\n"
                + " where Shipping.shippingId = :shippingId";
    }

    private static final String FIND_BY_PROPOSAL_ID() {
        return "select  " + SqlTableMapper.getShippingTable()
                + ", (select count(*) from BLSample where BLSample.containerId = Container.containerId) as sampleCount, "
                + SqlTableMapper.getContainerTable()
                + " , (select count(*) from StockSolution where Dewar.dewarId = StockSolution.boxId) as stockSolutionCount, "
                + SqlTableMapper.getDewarTable() + " from Shipping \r\n"
                + " left join Dewar on Dewar.shippingId = Shipping.shippingId \r\n"
                + " left join Container on Dewar.dewarId = Container.dewarId \r\n"
                + " where Shipping.proposalId = :proposalId";
    }

    // Generic HQL request to find all instances of Shipping3
    // TODO choose between left/inner join
    private static final String FIND_ALL() {
        return "from Shipping3VO vo ";
    }

    private final static String UPDATE_PROPOSALID_STATEMENT = " update Shipping  set proposalId = :newProposalId "
            + " WHERE proposalId = :oldProposalId"; // 2 old value to be replaced

    private final static String COUNT_SHIPPING_INFO = "SELECT COUNT(DISTINCT(histo.dewarTransportHistoryId)) eventsNumber, "
            + " count(DISTINCT(bls.blSampleId)) samplesNumber " + "FROM Shipping s  "
            + " LEFT JOIN Dewar d ON (d.shippingId=s.shippingId) "
            + "  LEFT JOIN Container c ON c.dewarId = d.dewarId "
            + "    LEFT JOIN BLSample bls ON bls.containerId = c.containerId "
            + "  LEFT JOIN DewarTransportHistory histo ON (histo.dewarId = d.dewarId) " +
            // TODO use the Constants -- problem while deploying app.
            // "AND (histo.dewarStatus='"+ Constants.SHIPPING_STATUS_AT_ESRF + "' " +
            // " OR histo.dewarStatus='" + Constants.SHIPPING_STATUS_SENT_TO_USER + "')" +
            "AND (histo.dewarStatus='atESRF' " + "OR histo.dewarStatus='sent to User') "
            + "WHERE s.shippingId = :shippingId GROUP BY s.shippingId ";

    @PersistenceContext(unitName = "ispyb_db")
    private EntityManager entityManager;

    public Shipping3ServiceBean() {
    };

    /**
     * Create new Shipping3.
     * 
     * @param vo
     *            the entity to persist.
     * @return the persisted entity.
     */
    public Shipping3VO create(final Shipping3VO vo) throws Exception {

        checkCreateChangeRemoveAccess();
        // TODO Edit this business code
        this.checkAndCompleteData(vo, true);
        this.entityManager.persist(vo);
        return vo;
    }

    /**
     * Update the Shipping3 data.
     * 
     * @param vo
     *            the entity data to update.
     * @return the updated entity.
     */
    public Shipping3VO update(final Shipping3VO vo) throws Exception {

        checkCreateChangeRemoveAccess();
        this.checkAndCompleteData(vo, false);
        return entityManager.merge(vo);
    }

    /**
     * Remove the Shipping3 from its pk
     * 
     * @param vo
     *            the entity to remove.
     */
    public void deleteByPk(final Integer pk) throws Exception {

        checkCreateChangeRemoveAccess();
        Shipping3VO vo = findByPk(pk, true);
        delete(vo);
    }

    /**
     * Remove the Shipping3
     * 
     * @param vo
     *            the entity to remove.
     */
    public void delete(final Shipping3VO vo) throws Exception {

        checkCreateChangeRemoveAccess();
        entityManager.remove(vo);
    }

    /**
     * Finds a Scientist entity by its primary key and set linked value objects if necessary
     * 
     * @param pk
     *            the primary key
     * @param withLink1
     * @param withLink2
     * @return the Shipping3 value object
     */
    public Shipping3VO findByPk(final Integer pk, final boolean withDewars) throws Exception {

        checkCreateChangeRemoveAccess();
        try {
            return (Shipping3VO) entityManager.createQuery(FIND_BY_PK(withDewars)).setParameter("pk", pk)
                    .getSingleResult();
        } catch (NoResultException e) {
            return null;
        }
    }

    public Shipping3VO findByPk(final Integer pk, final boolean withDewars, final boolean withcontainers,
            final boolean withSamples) throws Exception {

        checkCreateChangeRemoveAccess();
        try {
            return (Shipping3VO) entityManager.createQuery(FIND_BY_PK(withDewars, withcontainers, withSamples))
                    .setParameter("pk", pk).getSingleResult();
        } catch (NoResultException e) {
            return null;
        }
    }

    public String findSerialShippingByPk(final Integer pk, final boolean withDewars, final boolean withcontainers,
            final boolean withSamples, final boolean withSubSamples) throws Exception {

        checkCreateChangeRemoveAccess();
        String st = null;
        Shipping3VO vo = this.findByPk(pk, withDewars, withcontainers, withSamples, withSubSamples);
        if (vo != null) {
            st = serialize(vo);
        }
        return st;
    }

    public Shipping3VO findByPk(final Integer pk, final boolean withDewars, final boolean withcontainers,
            final boolean withSamples, final boolean withSubSamples) throws Exception {

        checkCreateChangeRemoveAccess();
        try {
            return (Shipping3VO) entityManager
                    .createQuery(FIND_BY_PK(withDewars, withcontainers, withSamples, withSubSamples))
                    .setParameter("pk", pk).getSingleResult();
        } catch (NoResultException e) {
            return null;
        }
    }

    @Override
    public List<Map<String, Object>> getShippingById(final Integer shippingId) throws Exception {

        checkCreateChangeRemoveAccess();
        String mySQLQuery = FIND_BY_SHIPPING_ID();
        Session session = (Session) this.entityManager.getDelegate();
        SQLQuery query = session.createSQLQuery(mySQLQuery);
        query.setParameter("shippingId", shippingId);
        query.setResultTransformer(AliasToEntityMapResultTransformer.INSTANCE);
        List<Map<String, Object>> aliasToValueMapList = query.list();
        return aliasToValueMapList;
    }

    @Override
    public List<Map<String, Object>> getShippingByProposalId(final Integer proposalId) throws Exception {

        checkCreateChangeRemoveAccess();
        String mySQLQuery = FIND_BY_PROPOSAL_ID();
        Session session = (Session) this.entityManager.getDelegate();
        SQLQuery query = session.createSQLQuery(mySQLQuery);
        query.setParameter("proposalId", proposalId);
        query.setResultTransformer(AliasToEntityMapResultTransformer.INSTANCE);
        List<Map<String, Object>> aliasToValueMapList = query.list();
        return aliasToValueMapList;
    }

    // TODO remove following method if not adequate
    /**
     * Find all Shipping3s and set linked value objects if necessary
     * 
     * @param withLink1
     * @param withLink2
     */
    @SuppressWarnings("unchecked")
    public List<Shipping3VO> findAll() throws Exception {

        List<Shipping3VO> foundEntities = entityManager.createQuery(FIND_ALL()).getResultList();
        return foundEntities;
    }

    @SuppressWarnings("unchecked")
    public List<Shipping3VO> findFiltered(final Integer proposalId, final String type) throws Exception {

        Session session = (Session) this.entityManager.getDelegate();

        Criteria crit = session.createCriteria(Proposal3VO.class);

        crit.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); // DISTINCT RESULTS !

        if (type != null && !type.isEmpty()) {
            crit.add(Restrictions.like("shippingType", type));
        }

        if (proposalId != null) {
            crit.createCriteria("proposalVO");
            crit.add(Restrictions.eq("proposalId", proposalId));
        }

        crit.addOrder(Order.desc("shippingId"));

        List<Shipping3VO> foundEntities = crit.list();
        return foundEntities;
    }

    /**
     * Check if user has access rights to create, change and remove Shipping3 entities. If not set rollback only and throw
     * AccessDeniedException
     * 
     * @throws AccessDeniedException
     */
    private void checkCreateChangeRemoveAccess() throws Exception {
        // AuthorizationServiceLocal autService = (AuthorizationServiceLocal)
        // ServiceLocator.getInstance().getService(AuthorizationServiceLocalHome.class); // TODO change method
        // to the one checking the needed access rights
        // autService.checkUserRightToChangeAdminData();
    }

    @SuppressWarnings("unchecked")
    @Override
    public List<Shipping3VO> findByStatus(final String status, final java.util.Date dateStart,
            final boolean withDewars) throws Exception {

        Session session = (Session) this.entityManager.getDelegate();
        Criteria criteria = session.createCriteria(Shipping3VO.class);
        if (status != null && !status.isEmpty()) {
            criteria.add(Restrictions.like("shippingStatus", status));
        }

        if (dateStart != null) {
            criteria.add(Restrictions.ge("creationDate", dateStart));
        }

        if (withDewars) {
            criteria.setFetchMode("dewarVOs", FetchMode.JOIN);
        }
        criteria.addOrder(Order.desc("shippingId")).setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); // DISTINCT
        // RESULTS !

        return criteria.list();
    }

    @SuppressWarnings("unchecked")
    @Override
    public List<Shipping3VO> findByProposal(final Integer userProposalId, final boolean withDewars)
            throws Exception {

        Session session = (Session) this.entityManager.getDelegate();
        Criteria criteria = session.createCriteria(Shipping3VO.class);

        if (userProposalId != null) {
            Criteria subCritProposal = criteria.createCriteria("proposalVO");
            subCritProposal.add(Restrictions.eq("proposalId", userProposalId));
        }

        if (withDewars) {
            criteria.setFetchMode("dewarVOs", FetchMode.JOIN);
        }
        criteria.addOrder(Order.desc("creationDate"));
        criteria.addOrder(Order.desc("shippingId"));
        criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
        return criteria.list();
    }

    @SuppressWarnings("unchecked")
    @Override
    public List<Shipping3VO> findByProposal(final Integer proposalId, final boolean fetchDewars,
            final boolean fetchContainers, final boolean fetchSamples) throws Exception {

        try {
            return entityManager.createQuery(FIND_BY_PROPOSAL_ID(fetchDewars, fetchContainers, fetchSamples))
                    .setParameter("proposalId", proposalId).getResultList();
        } catch (NoResultException e) {
            return null;
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public List<Shipping3VO> findByCreationDate(final Date firstDate, final boolean withDewars) throws Exception {

        Session session = (Session) this.entityManager.getDelegate();
        Criteria criteria = session.createCriteria(Shipping3VO.class);

        if (firstDate != null) {
            criteria.add(Restrictions.ge("creationDate", firstDate));
        }

        if (withDewars) {
            criteria.setFetchMode("dewarVOs", FetchMode.JOIN);
        }
        criteria.addOrder(Order.desc("creationDate"));
        criteria.addOrder(Order.desc("shippingId"));
        criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
        return criteria.list();
    }

    @SuppressWarnings("unchecked")
    @Override
    public List<Shipping3VO> findByCreationDateInterval(final Date firstDate, final Date endDate) throws Exception {

        Session session = (Session) this.entityManager.getDelegate();
        Criteria criteria = session.createCriteria(Shipping3VO.class);

        if (firstDate != null) {
            criteria.add(Restrictions.ge("creationDate", firstDate));
        }

        if (endDate != null) {
            criteria.add(Restrictions.le("creationDate", endDate));
        }

        criteria.addOrder(Order.desc("creationDate"));
        criteria.addOrder(Order.desc("shippingId"));
        criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
        return criteria.list();
    }

    @SuppressWarnings("unchecked")
    @Override
    public List<Shipping3VO> findByBeamLineOperator(final String beamlineOperatorSiteNumber,
            final boolean withDewars) throws Exception {

        Session session = (Session) this.entityManager.getDelegate();
        Criteria criteria = session.createCriteria(Shipping3VO.class);

        if (beamlineOperatorSiteNumber != null) {
            Criteria sessionCriteria = criteria.createCriteria("sessions")
                    .add(Restrictions.eq("operatorSiteNumber", beamlineOperatorSiteNumber));
            // .addOrder(Order.desc(propertyName))
            if (withDewars) {
                criteria.setFetchMode("dewarVOs", FetchMode.JOIN);
            }
            criteria.addOrder(Order.desc("creationDate"));
            criteria.addOrder(Order.desc("shippingId"));
            criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
            return criteria.list();
        } else
            return null;
    }

    @Override
    public List<Shipping3VO> findByProposalCode(final String proposalCode, final boolean withDewars)
            throws Exception {

        return this.findFiltered(null, null, proposalCode, null, null, null, null, null, withDewars);
    }

    @SuppressWarnings("unchecked")
    @Override
    public List<Shipping3VO> findFiltered(final Integer proposalId, final String shippingName,
            final String proposalCode, final String proposalNumber, final String mainProposer, final Date date,
            final Date date2, final String operatorSiteNumber, final boolean withDewars) throws Exception {

        Session session = (Session) this.entityManager.getDelegate();
        Criteria criteria = session.createCriteria(Shipping3VO.class);

        if ((shippingName != null) && (!shippingName.isEmpty())) {
            criteria.add(Restrictions.like("shippingName", shippingName));
        }

        if (date != null) {
            criteria.add(Restrictions.ge("creationDate", date));
        }

        if (date2 != null) {
            criteria.add(Restrictions.le("creationDate", date2));
        }

        if (proposalId != null || proposalCode != null || mainProposer != null) {
            Criteria subCritProposal = criteria.createCriteria("proposalVO");
            if (proposalId != null) {
                subCritProposal.add(Restrictions.eq("proposalId", proposalId));
            }
            if (proposalId == null && proposalCode != null && !proposalCode.isEmpty()) {
                subCritProposal.add(Restrictions.like("code", proposalCode).ignoreCase());
            }
            if ((mainProposer != null) && (!mainProposer.isEmpty())) {
                Criteria subCritPerson = subCritProposal.createCriteria("personVO");
                subCritPerson.add(Restrictions.like("familyName", mainProposer).ignoreCase());
            }

        }

        if (operatorSiteNumber != null) {
            criteria.createAlias("sessions", "se");
            criteria.add(Restrictions.eq("se.operatorSiteNumber", operatorSiteNumber));
        }

        if (withDewars) {
            criteria.setFetchMode("dewarVOs", FetchMode.JOIN);
        }
        criteria.addOrder(Order.desc("creationDate"));
        criteria.addOrder(Order.desc("shippingId"));
        criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
        return criteria.list();
    }

    @Override
    public List<Shipping3VO> findByCustomQuery(final Integer proposalId, final String shippingName,
            final String proposalCode, final String proposalNumber, final String mainProposer, final Date date,
            final Date date2, final String operatorSiteNumber) throws Exception {

        return this.findFiltered(proposalId, shippingName, proposalCode, proposalNumber, mainProposer, date, date2,
                operatorSiteNumber, false);
    }

    /**
     * update the proposalId, returns the nb of rows updated
     * 
     * @param newProposalId
     * @param oldProposalId
     * @return
     * @throws Exception
     */
    public Integer updateProposalId(final Integer newProposalId, final Integer oldProposalId) throws Exception {

        int nbUpdated = 0;
        Query query = entityManager.createNativeQuery(UPDATE_PROPOSALID_STATEMENT)
                .setParameter("newProposalId", newProposalId).setParameter("oldProposalId", oldProposalId);
        nbUpdated = query.executeUpdate();

        return new Integer(nbUpdated);
    }

    public int deleteAllSamplesAndContainersForShipping(Integer shippingId) throws Exception {
        Ejb3ServiceLocator ejb3ServiceLocator = Ejb3ServiceLocator.getInstance();
        Dewar3Service dewarService = (Dewar3Service) ejb3ServiceLocator.getLocalService(Dewar3Service.class);
        Container3Service containerService = (Container3Service) ejb3ServiceLocator
                .getLocalService(Container3Service.class);

        int nb = 0;
        Shipping3VO ship = this.findByPk(shippingId, true);
        Set<Dewar3VO> dewars = ship.getDewarVOs();
        for (Dewar3VO dewar3vo : dewars) {
            Dewar3VO dewar = dewarService.findByPk(dewar3vo.getDewarId(), true, true);
            Set<Container3VO> containers = dewar.getContainerVOs();
            for (Container3VO container3vo : containers) {
                containerService.deleteByPk(container3vo.getContainerId());
                nb = nb + 1;
            }
        }
        return nb;
    }

    @Override
    public List<Shipping3VO> findByProposalType(String proposalType) throws Exception {
        return this.findFiltered(null, null, proposalType, null, null, null, null, null, false);
    }

    @Override
    public List<Shipping3VO> findByProposalCodeAndDates(String proposalType, Date firstDate, Date endDate)
            throws Exception {
        return this.findFiltered(null, null, proposalType, null, null, firstDate, endDate, null, false);
    }

    @SuppressWarnings("unchecked")
    @Override
    public List<Shipping3VO> findByIsStorageShipping(final Boolean isStorageShipping) throws Exception {

        Session session = (Session) this.entityManager.getDelegate();
        Criteria criteria = session.createCriteria(Shipping3VO.class);
        criteria.add(Restrictions.eq("isStorageShipping", isStorageShipping));
        return criteria.list();
    }

    public Shipping3VO loadEager(Shipping3VO vo) throws Exception {
        Shipping3VO newVO = this.findByPk(vo.getShippingId(), true);
        return newVO;
    }

    public Integer[] countShippingInfo(final Integer shippingId) throws Exception {
        Query query = entityManager.createNativeQuery(COUNT_SHIPPING_INFO).setParameter("shippingId", shippingId);
        List orders = query.getResultList();
        int nb = orders.size();
        Integer nbSamples = 0;
        Integer nbDewarHistory = 0;
        Integer[] tab = new Integer[2];
        if (nb > 0) {
            Object[] o = (Object[]) orders.get(0);
            nbDewarHistory = ((BigInteger) o[0]).intValue();
            nbSamples = ((BigInteger) o[1]).intValue();
        }
        tab[0] = nbDewarHistory;
        tab[1] = nbSamples;
        return tab;
    }

    /*
     * (non-Javadoc)
     * 
     * @see ispyb.server.common.services.shipping.Shipping3Service#findByPk(java.lang.Integer, boolean, boolean)
     */
    @Override
    public Shipping3VO findByPk(final Integer pk, final boolean withDewars, final boolean withSession)
            throws Exception {

        checkCreateChangeRemoveAccess();
        try {
            if (withSession) {
                return (Shipping3VO) entityManager.createQuery(FIND_BY_PK(withDewars, withSession))
                        .setParameter("pk", pk).getSingleResult();
            }
            return (Shipping3VO) entityManager.createQuery(FIND_BY_PK(withDewars)).setParameter("pk", pk)
                    .getSingleResult();
        } catch (NoResultException e) {
            return null;
        }
    }

    /* Private methods ------------------------------------------------------ */

    public static String serialize(Shipping3VO shipping) {
        Gson gson = new GsonBuilder().excludeFieldsWithModifiers(Modifier.PRIVATE).serializeNulls().create();
        return gson.toJson(shipping);
    }

    /**
     * Checks the data for integrity. E.g. if references and categories exist.
     * 
     * @param vo
     *            the data to check
     * @param create
     *            should be true if the value object is just being created in the DB, this avoids some checks like
     *            testing the primary key
     * @exception VOValidateException
     *                if data is not correct
     */
    private void checkAndCompleteData(Shipping3VO vo, boolean create) throws Exception {
        if (create) {
            if (vo.getShippingId() != null) {
                throw new IllegalArgumentException(
                        "Primary key is already set! This must be done automatically. Please, set it to null!");
            }
        } else {
            if (vo.getShippingId() == null) {
                throw new IllegalArgumentException("Primary key is not set for update!");
            }
        }
        // check value object
        vo.checkValues(create);
        // TODO check primary keys for existence in DB
    }

}