AgentRateRepositoryImpl.java

package com.tradecloud.repository.rate.impl;

import com.tradecloud.domain.costing.CostingType;
import com.tradecloud.domain.infrastructure.persistence.CriteriaBuilder;
import com.tradecloud.domain.model.organisationalunit.OrganisationalUnit;
import com.tradecloud.domain.rate.AgentRate;
import com.tradecloud.domain.rate.AgentRateCosting;
import com.tradecloud.domain.supplier.Supplier;
import com.tradecloud.dto.rate.AgentRateSearch;
import com.tradecloud.repository.rate.AgentRateRepository;
import com.tradecloud.repository.utils.CriteriaBuilder2;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.ProjectionList;
import org.hibernate.criterion.Restrictions;
import org.hibernate.transform.AliasToBeanResultTransformer;
import org.springframework.stereotype.Repository;

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

@Repository(value = "agentRateRepository")
public class AgentRateRepositoryImpl extends BaseRateRepository<AgentRate, AgentRateSearch> implements AgentRateRepository {

    private DetachedCriteria buildBaseCriteria(AgentRateSearch search) {
        DetachedCriteria criteria = DetachedCriteria.forClass(AgentRate.class);

        if (search.isSpecificSearch()) {
            CriteriaBuilder.addExactMatch(criteria, "costLine", search.getCostLine());
            CriteriaBuilder.addExactMatch(criteria, "organisationalUnit", search.getOrganisationalUnit());
            CriteriaBuilder.addExactMatch(criteria, "supplier", search.getSupplier());
            CriteriaBuilder.addExactMatch(criteria, "agent", search.getAgent());
            CriteriaBuilder.addExactMatch(criteria, "costingType", search.getCostingType());
            CriteriaBuilder.addExactMatch(criteria, "rateUnit", search.getRateUnit());
            CriteriaBuilder.addExactMatch(criteria, "currency", search.getCurrency());

        } else {
            CriteriaBuilder.addEqRestriction(criteria, "costLine", search.getCostLine());
            CriteriaBuilder.addEqRestriction(criteria, "organisationalUnit", search.getOrganisationalUnit());
            CriteriaBuilder.addEqRestriction(criteria, "supplier", search.getSupplier());
            CriteriaBuilder.addEqRestriction(criteria, "agent", search.getAgent());
            CriteriaBuilder.addEqRestriction(criteria, "costingType", search.getCostingType());
            CriteriaBuilder.addEqRestriction(criteria, "currency", search.getCurrency());
            CriteriaBuilder.addEqRestriction(criteria, "rateUnit", search.getRateUnit());
        }
        CriteriaBuilder.addEqRestriction(criteria, "costCompareOnly", search.isCostCompareOnly());
        return criteria;
    }

    @Override
    public List<AgentRate> search(AgentRateSearch 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"));

        //List<AgentRate> results = criteria.getExecutableCriteria(getSessionCustom()).list();
        //return results;
        return getExecutableCriteriaList(criteria, search.getSearchMetaParams());
    }

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

        return getExecutableCriteriaCount(criteria);
    }

    @Override
    public List<AgentRate> searchByClosestEffectiveDate(AgentRateSearch search) {

        DetachedCriteria criteria = buildBaseCriteria(search);

        CriteriaBuilder.addDateLessOrEqualRangeCriteria(criteria, "effectiveDate", search.getEffectiveDateLower());
        criteria.addOrder(Order.desc("agent")).addOrder(Order.desc("organisationalUnit")).addOrder(Order.desc("supplier"));
        criteria.addOrder(org.hibernate.criterion.Order.desc("effectiveDate"));

        List<AgentRate> results = criteria.getExecutableCriteria(getSessionCustom()).list();
        if (results.size() > 1) {
            List<AgentRate> list = new ArrayList<AgentRate>();
            list.add(results.get(0));
            return list;
        }
        return results;
    }

    @Override
    public void save(AgentRate agentRate) {
        super.save(agentRate);
    }

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

    @Override
    public AgentRate searchByOrderOfPriorityCosting(AgentRateSearch search) {
        DetachedCriteria criteria = DetachedCriteria.forClass(AgentRate.class);
        setCostingProjections(criteria);
        return searchByOrderOfPriority(search, criteria);
    }

    //DO not return heavy objects here, if you must then return id or list of ids.
    private  void setCostingProjections(DetachedCriteria criteria) {
        ProjectionList projections = costingProjectionsCommon();
        criteria.setProjection(projections);
        criteria.setResultTransformer(new AliasToBeanResultTransformer(AgentRateCosting.class));
    }

    private AgentRate searchByOrderOfPriority(AgentRateSearch search, DetachedCriteria criteria) {
        if (search.getCostLine() == null) {
            throw new IllegalArgumentException("Rate search must contain CostLine");
        }

        CriteriaBuilder.addEqRestriction(criteria, "costLine", search.getCostLine());
        CriteriaBuilder.addEqRestriction(criteria, "costingType", search.getCostingType());
        CriteriaBuilder.addEqRestriction(criteria, "costCompareOnly", search.isCostCompareOnly());

        CriteriaBuilder.addDisjunctionIn(criteria, "organisationalUnit", findApplicableOrgs(search));
        CriteriaBuilder.addDisjunction(criteria, "supplier", search.getSupplier());
        CriteriaBuilder.addDisjunction(criteria, "agent", search.getAgent());
        setRateUnitAndCurrency(search, criteria);

        DetachedCriteria tierCriteria = findOrgTierCriteria(search, criteria);

        CriteriaBuilder2.addRateOrderOfPriority(criteria, search, null, tierCriteria);
        CriteriaBuilder.addDateLessOrEqualRangeCriteria(criteria, "effectiveDate", search.getEffectiveDateLower());

        List<AgentRate> results = getExecutableCriteriaList(criteria, null);

        return results.size() == 0 ? null : results.get(0);
    }

//    @Override
//    public List<AgentRate> findAgentCostLineRates(AgentRateSearch search) {
//        if (search.getCostLine() == null) {
//            throw new RuntimeException("Rate search must contain CostLine");
//        }
//
//        DetachedCriteria criteria = DetachedCriteria.forClass(AgentRate.class);
//        CriteriaBuilder.addEqRestriction(criteria, "costLine", search.getCostLine());
//        CriteriaBuilder.addEqRestriction(criteria, "costingType", search.getCostingType());
//
//        if (search.getOrganisationalUnit() != null) {
//            CriteriaBuilder.addDisjunction(criteria, "organisationalUnit", search.getOrganisationalUnit());
//        }
//        if (search.getSupplier() != null) {
//            CriteriaBuilder.addDisjunction(criteria, "supplier", search.getSupplier());
//        }
//        if (search.getAgent() != null) {
//            CriteriaBuilder.addDisjunction(criteria, "agent", search.getAgent());
//        }
//
//        CriteriaBuilder.addDateLessOrEqualRangeCriteria(criteria, "effectiveDate", search.getEffectiveDateUpper());
//
//        criteria.addOrder(Order.desc("costLine")).addOrder(Order.desc("effectiveDate")).addOrder(Order.asc("id"));
//
//        return criteria.getExecutableCriteria(getSessionCustom()).list();
//    }

    @Override
    public List<AgentRate> findAgentRates(String costLine, CostingType costingType, Date effectiveDate,
                                          Supplier supplier, List<OrganisationalUnit> organisationalUnits) {
        if (costLine == null) {
            throw new RuntimeException("CostLine is mandatory");
        } else if (costingType == null) {
            throw new RuntimeException("CostingType is mandatory");
        } else if (supplier == null) {
            throw new RuntimeException("Supplier is mandatory");
        } else if (organisationalUnits == null) {
            throw new RuntimeException("OrganisationalUnits is mandatory");
        }

        DetachedCriteria criteria = DetachedCriteria.forClass(AgentRate.class);
        CriteriaBuilder.addEqRestriction(criteria, "costLine", costLine);
        CriteriaBuilder.addEqRestriction(criteria, "costingType", costingType);
        CriteriaBuilder.addEqRestriction(criteria, "costCompareOnly", false);
        if (organisationalUnits.size() > 0) {
            criteria.add(Restrictions.disjunction().
                    add(Restrictions.isNull("organisationalUnit")).
                    add(Restrictions.in("organisationalUnit", organisationalUnits)));
        }

        CriteriaBuilder.addDisjunction(criteria, "supplier", supplier);

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

        criteria.addOrder(Order.desc("costLine")).addOrder(Order.desc("effectiveDate")).addOrder(Order.asc("id"));

        return criteria.getExecutableCriteria(getSessionCustom()).list();
    }
}