FreightRateRepositoryImpl.java

package com.tradecloud.repository.rate.impl;

import com.tradecloud.domain.base.utils.MathUtils;
import com.tradecloud.domain.infrastructure.persistence.CriteriaBuilder;
import com.tradecloud.domain.rate.FreightRate;
import com.tradecloud.domain.rate.FreightRateCosting;
import com.tradecloud.dto.rate.FreightRateSearch;
import com.tradecloud.repository.rate.FreightRateRepository;
import com.tradecloud.repository.utils.CriteriaBuilder2;
import org.apache.log4j.Logger;
import org.hibernate.criterion.*;
import org.hibernate.transform.AliasToBeanResultTransformer;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

@Repository(value = "freightRateRepository")
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT)
public class FreightRateRepositoryImpl extends BaseRateRepository<FreightRate, FreightRateSearch> implements FreightRateRepository {

    private static final long serialVersionUID = 1L;
    private static final Logger log = Logger.getLogger(FreightRateRepositoryImpl.class);

    private DetachedCriteria buildBaseCriteria(FreightRateSearch search) {
        DetachedCriteria criteria = DetachedCriteria.forClass(FreightRate.class);

        if (search.isSpecificSearch()) {
            CriteriaBuilder.addExactMatch(criteria, "costLine", search.getCostLine());
            CriteriaBuilder.addExactMatch(criteria, "shippingMode", search.getShippingMode());
            CriteriaBuilder.addExactMatch(criteria, "multiModalShippingMode", search.getMultiModalShippingMode());
            CriteriaBuilder.addExactMatch(criteria, "containerType", search.getContainerType());
            CriteriaBuilder.addExactMatch(criteria, "placeOfDischarge", search.getPlaceOfDischarge());
            CriteriaBuilder.addExactMatch(criteria, "placeOfLoading", search.getPlaceOfLoading());
            CriteriaBuilder.addExactMatch(criteria, "freightForwarder", search.getFreightForwarder());
            CriteriaBuilder.addExactMatch(criteria, "country", search.getCountry());
            CriteriaBuilder.addExactMatch(criteria, "carrier", search.getCarrier());
            CriteriaBuilder.addExactMatch(criteria, "costingType", search.getCostingType());
            CriteriaBuilder.addExactMatch(criteria, "organisationalUnit", search.getOrganisationalUnit());
            CriteriaBuilder.addExactMatch(criteria, "rateUnit", search.getRateUnit());
            CriteriaBuilder.addExactMatch(criteria, "currency", search.getCurrency());
        } else {
            CriteriaBuilder.addEqRestriction(criteria, "organisationalUnit", search.getOrganisationalUnit());
            CriteriaBuilder.addEqRestriction(criteria, "costLine", search.getCostLine());
            CriteriaBuilder.addEqRestriction(criteria, "shippingMode", search.getShippingMode());
            CriteriaBuilder.addEqRestriction(criteria, "multiModalShippingMode", search.getMultiModalShippingMode());
            CriteriaBuilder.addEqRestriction(criteria, "containerType", search.getContainerType());
            CriteriaBuilder.addEqRestriction(criteria, "placeOfDischarge", search.getPlaceOfDischarge());
            CriteriaBuilder.addEqRestriction(criteria, "placeOfLoading", search.getPlaceOfLoading());
            CriteriaBuilder.addEqRestriction(criteria, "freightForwarder", search.getFreightForwarder());
            CriteriaBuilder.addEqRestriction(criteria, "country", search.getCountry());
            CriteriaBuilder.addEqRestriction(criteria, "carrier", search.getCarrier());
            CriteriaBuilder.addEqRestriction(criteria, "costingType", search.getCostingType());
            CriteriaBuilder.addEqRestriction(criteria, "rateUnit", search.getRateUnit());
            CriteriaBuilder.addEqRestriction(criteria, "currency", search.getCurrency());
        }
        CriteriaBuilder.addEqRestriction(criteria, "costCompareOnly", search.isCostCompareOnly());
        if (search.getWeight() != null && !MathUtils.isZero(search.getWeight())) {
            criteria.add(Restrictions.disjunction().add(Restrictions.isNull("weightFrom")).add(Restrictions.le("weightFrom", search.getWeight())));
            criteria.add(Restrictions.disjunction().add(Restrictions.isNull("weightTo")).add(Restrictions.ge("weightTo", search.getWeight())));
        }

        if (search.getWeightFrom() != null && !MathUtils.isZero(search.getWeightFrom())) {
            CriteriaBuilder.addEqRestriction(criteria, "weightFrom", search.getWeightFrom());
        }

        if (search.getWeightTo() != null && !MathUtils.isZero(search.getWeightTo())) {
            CriteriaBuilder.addEqRestriction(criteria, "weightTo", search.getWeightTo());
        }

        return criteria;
    }

    @Override
    public List<FreightRate> search(FreightRateSearch search) {
        DetachedCriteria criteria = buildBaseCriteria(search);
        CriteriaBuilder.addDateGreaterOrEqualRangeCriteria(criteria, "effectiveDate", search.getEffectiveDateLower());
        CriteriaBuilder.addDateLessOrEqualRangeCriteria(criteria, "effectiveDate", search.getEffectiveDateUpper());
        criteria.addOrder(Order.desc("costLine")).addOrder(Order.desc("effectiveDate")).addOrder(Order.asc("id"));
        return getExecutableCriteriaList(criteria, search.getSearchMetaParams());
    }

    @Override
    public long count(FreightRateSearch search) {
        DetachedCriteria criteria = buildBaseCriteria(search);
        CriteriaBuilder.addDateGreaterOrEqualRangeCriteria(criteria, "effectiveDate", search.getEffectiveDateLower());
        CriteriaBuilder.addDateLessOrEqualRangeCriteria(criteria, "effectiveDate", search.getEffectiveDateUpper());

        return getExecutableCriteriaCount(criteria);
    }

    @Override
    public List<FreightRate> searchByClosestEffectiveDate(FreightRateSearch search) {

        DetachedCriteria criteria = buildBaseCriteria(search);

        CriteriaBuilder.addDateLessOrEqualRangeCriteria(criteria, "effectiveDate", search.getEffectiveDateLower());

        criteria.addOrder(org.hibernate.criterion.Order.desc("effectiveDate"));

        // @SuppressWarnings("unchecked")
        // List<Rate> results = criteria.getExecutableCriteria(getSessionFlushMode()).list();
        List<FreightRate> results = getExecutableCriteriaList(criteria, null);

        if (results.size() > 1) {
            List<FreightRate> list = new ArrayList<FreightRate>();
            list.add(results.get(0));
            // System.out.println(results.get(0).getCostLine()+", "+results.get(0).getId()+", "+results.get(0).getRate());
            return list;
        }
        return results;
    }

    @Override
    public FreightRate searchByOrderOfPriority(FreightRateSearch search) {
        DetachedCriteria criteria = DetachedCriteria.forClass(FreightRate.class);
        return searchByOrderOfPriority(search, criteria);
    }

    public FreightRate searchByOrderOfPriorityCosting(FreightRateSearch search) {
        DetachedCriteria criteria = DetachedCriteria.forClass(FreightRate.class);
        setCostingProjections(criteria);
        return searchByOrderOfPriority(search, criteria);
    }

    private FreightRate searchByOrderOfPriority(FreightRateSearch search, DetachedCriteria criteria) {
        if (search.getCostLine() == null) {
            throw new RuntimeException("Rate search must contain CostLine");
        }
        CriteriaBuilder.addEqRestriction(criteria, "costLine", search.getCostLine());
        CriteriaBuilder.addEqRestriction(criteria, "shippingMode", search.getShippingMode());
        CriteriaBuilder.addDisjunction(criteria, "multiModalShippingMode", search.getMultiModalShippingMode());
        CriteriaBuilder.addEqRestriction(criteria, "costingType", search.getCostingType());
        CriteriaBuilder.addEqRestriction(criteria, "costCompareOnly", search.isCostCompareOnly());
        CriteriaBuilder.addDisjunction(criteria, "containerType", search.getContainerType());
        CriteriaBuilder.addDisjunction(criteria, "placeOfDischarge", search.getPlaceOfDischarge());
        CriteriaBuilder.addDisjunction(criteria, "placeOfLoading", search.getPlaceOfLoading());
        CriteriaBuilder.addDisjunction(criteria, "freightForwarder", search.getFreightForwarder());
        CriteriaBuilder.addDisjunction(criteria, "country", search.getCountry());
        CriteriaBuilder.addDisjunction(criteria, "carrier", search.getCarrier());
        setRateUnitAndCurrency(search, criteria);
        CriteriaBuilder.addDisjunctionIn(criteria, "organisationalUnit", findApplicableOrgs(search));
        CriteriaBuilder2.addRateOrderOfPriority(criteria, search, new String[]{"shippingMode"}, null);
        if (search.getMultiModalShippingMode() != null) {
            CriteriaBuilder2.addRateOrderOfPriority(criteria, search, new String[]{"multiModalShippingMode"}, null);
        }
        CriteriaBuilder.addDateLessOrEqualRangeCriteria(criteria, "effectiveDate", search.getEffectiveDateLower());

        if (search.getWeight() != null && !MathUtils.isZero(search.getWeight())) {
            criteria.add(Restrictions.disjunction().add(Restrictions.isNull("weightFrom")).add(Restrictions.le("weightFrom", search.getWeight())));
            criteria.add(Restrictions.disjunction().add(Restrictions.isNull("weightTo")).add(Restrictions.ge("weightTo", search.getWeight())));
        }

        List<FreightRate> results = criteria.getExecutableCriteria(getSessionCustom()).list();
        return results.size() == 0 ? null : results.get(0);
    }

    //DO not return heavy objects here, if you must then return id or list of ids.
    private  void setCostingProjections(DetachedCriteria criteria) {

        ProjectionList projections = costingProjectionsCommon()
                .add(Projections.property("maxValue"), "maxValue")
                .add(Projections.property("minValue"), "minValue")
                .add(Projections.property("weightFrom"), "weightFrom")
                .add(Projections.property("weightTo"), "weightTo");

        criteria.setProjection(projections);

        criteria.setResultTransformer(new AliasToBeanResultTransformer(FreightRateCosting.class));
    }

    @Override
    public void save(FreightRate freightRate) throws RuntimeException {
        super.save(freightRate);
    }
}