CreditorBillingRuleRepositoryImpl.java

package com.tradecloud.repository.creditorbilling.impl;

import com.tradecloud.domain.base.utils.ObjectUtil;
import com.tradecloud.domain.creditorbilling.rule.CreditorBillingRule;
import com.tradecloud.domain.infrastructure.persistence.CriteriaBuilder;
import com.tradecloud.dto.creditorbilling.CreditorBillingRuleSearch;
import com.tradecloud.repository.base.impl.RepositoryBaseImpl;
import com.tradecloud.repository.creditorbilling.CreditorBillingRuleRepository;
import java.io.Serializable;
import java.util.Collections;
import java.util.List;
import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.springframework.stereotype.Repository;

/**
 *
 * @author jon
 */
@Repository(value = "creditorBillingRuleRepository")
public class CreditorBillingRuleRepositoryImpl extends RepositoryBaseImpl<CreditorBillingRule, CreditorBillingRuleSearch>
    implements CreditorBillingRuleRepository {

    private final static Logger log = Logger.getLogger(CreditorBillingRuleRepositoryImpl.class);

    private final static String CARRIER = "carrier";
    private final static String FREIGHT_FORWARDER = "freightForwarder";
    private final static String INCOTERM = "incoterm";
    private final static String CONTAINER_TYPE = "containerType";
    private final static String EFFECTIVE_DATE = "effectiveDate";
    private final static String COUNTER_PARTY_ROLE = "counterPartyRole";
    private final static String RULE_TYPE = "creditorBillingRuleType";

    @Override
    public List<CreditorBillingRule> search(CreditorBillingRuleSearch search) {
        DetachedCriteria criteria = DetachedCriteria.forClass(CreditorBillingRule.class);

        CriteriaBuilder.addEqRestriction(criteria, CARRIER, search.getCarrier());
        CriteriaBuilder.addEqRestriction(criteria, FREIGHT_FORWARDER, search.getFreightForwarder());
        CriteriaBuilder.addEqRestriction(criteria, INCOTERM, search.getIncoterm());
        CriteriaBuilder.addEqRestriction(criteria, CONTAINER_TYPE, search.getContainerType());
        CriteriaBuilder.addEqRestriction(criteria, COUNTER_PARTY_ROLE, search.getCounterPartyRole());

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

    @Override
    public long count(CreditorBillingRuleSearch search) {
        return search(search).size();
    }

    @Override
    public List<CreditorBillingRule> searchByClosestEffectiveDate(CreditorBillingRuleSearch search) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public CreditorBillingRule searchByOrderOfPriority(CreditorBillingRuleSearch search) {
        // TODO. The actual sorting.

        DetachedCriteria criteria = DetachedCriteria.forClass(CreditorBillingRule.class);

        CriteriaBuilder.addEqRestriction(criteria, FREIGHT_FORWARDER, search.getFreightForwarder());
        CriteriaBuilder.addEqRestriction(criteria, INCOTERM, search.getIncoterm());
        CriteriaBuilder.addEqRestriction(criteria, RULE_TYPE, search.getType());

        CriteriaBuilder.addDisjunction(criteria, CARRIER, search.getCarrier());
        CriteriaBuilder.addDisjunction(criteria, CONTAINER_TYPE, search.getContainerType());

        List<CreditorBillingRule> rules = Collections.checkedList(criteria
                .getExecutableCriteria(getSessionCustom()).list(), CreditorBillingRule.class);

        return findMostSpecificRate(rules);
    }

    private CreditorBillingRule findMostSpecificRate(List<CreditorBillingRule> results){
        if (results.isEmpty())
            return null;
        else if (results.size() == 1)
            return results.get(0);

        CreditorBillingRule firstRate = results.get(0);
        int leastNumberOfNullValues = numberOfNullValues(firstRate);
        CreditorBillingRule mostSpecificRate = firstRate;

        for (int i=1; i<results.size(); i++){
            CreditorBillingRule clearingRate = results.get(i);

            int numberOfNullValues = numberOfNullValues((clearingRate));
            if (numberOfNullValues < leastNumberOfNullValues){
                mostSpecificRate = clearingRate;
            }
        }

        return mostSpecificRate;
    }

    private int numberOfNullValues(CreditorBillingRule rate){
        return ObjectUtil.countNulls(rate.getShippingMode(), rate.getContainerType(), rate.getCarrier(), rate.getFreightForwarder());
    }

    @Override
    public boolean exists(CreditorBillingRuleSearch search, Serializable excludingId) {
        // Has to have slightly different logic to the normal search, to get the exact match.
        // Also, can't use db unique constraints because of the nullable columns
        // TODO. Could probably be a named query. Not sure about the nulls though.
        DetachedCriteria criteria = DetachedCriteria.forClass(CreditorBillingRule.class);
        criteria.setProjection(Projections.rowCount());

        CriteriaBuilder.addExactMatch(criteria, FREIGHT_FORWARDER, search.getFreightForwarder());
        CriteriaBuilder.addExactMatch(criteria, INCOTERM, search.getIncoterm());

        CriteriaBuilder.addExactMatch(criteria, RULE_TYPE, search.getType());
        CriteriaBuilder.addExactMatch(criteria, CARRIER, search.getCarrier());
        CriteriaBuilder.addExactMatch(criteria, CONTAINER_TYPE, search.getContainerType());
        CriteriaBuilder.addExactMatch(criteria, EFFECTIVE_DATE, search.getEffectiveDate());

        CriteriaBuilder.addNotEqRestriction(criteria, "id", excludingId);

        Criteria c = criteria.getExecutableCriteria(getSessionCustom());
        c.setReadOnly(true);
        Object o = c.uniqueResult();
        return ((Long)o) != 0;
    }
}