CriteriaBuilder2.java

package com.tradecloud.repository.utils;

import com.tradecloud.domain.rate.RateLookupPriorityConfig;
import com.tradecloud.domain.rate.RateLookupPriorityType;
import com.tradecloud.dto.rate.RateSearch;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;

/**
 * TODO. CriteriaBuilder needs to move up from domain. Doing it slowly so there
 * aren't many merge hassles.
 *
 * @author jon
 */
public class CriteriaBuilder2 {

    public static void addRateOrderOfPriority(DetachedCriteria criteria, RateSearch rateSearch,
                                              String[] requiredOrderNames, DetachedCriteria tierCriteria) {

        // always first order element
        criteria.addOrder(Order.desc("effectiveDate"));

        if (requiredOrderNames != null) {
            for (String orderName : requiredOrderNames) {
                criteria.addOrder(Order.asc(orderName));
            }
        }

        if (rateSearch.getPriorityConfig() != null) {

            List<RateLookupPriorityConfig> priorities = rateSearch.getPriorityConfig();
            if (priorities != null && priorities.size() > 0) {
                //to avoid ConcurrentModificationException when sorting
                priorities=new ArrayList<>(priorities);
                Collections.sort(priorities);
            }

            for (RateLookupPriorityConfig lookupPriorityConfig : priorities) {
                if (lookupPriorityConfig.getActive() && lookupPriorityConfig.getCostLineTemplate().getCode().equals(rateSearch.getCostLine())) {

                    String dbString = lookupPriorityConfig.getRateLookupPriorityType().getDbString();

                    //lower (and valid) tiers have higher priority, so if:
                    /*
                        Org Struct:
                            A (business unit)
                                B (division)
                                    C (department)

                        Rate1: effective today, Org: A, Buyer: John
                        Rate2: effective today, Org: B, Buyer: -

                        And Priority Config is:
                        Org, Buyer

                        and Rate lookup done with B, then Rate2 will take priority over Rate1,
                            because it matches the org tier most closely

                        if the Priority Config was:
                        Buyer, Org

                        It would find Rate1 as Rate2 doesn't have a buyer
                     */

                    //special case for organisational unit
                    if (dbString.equals(RateLookupPriorityType.ORGANISATIONAL_UNIT.getDbString())) {
                        if (tierCriteria != null) {
                            tierCriteria.addOrder(Order.asc("level_"));
                        }
                    }

                    criteria.addOrder(Order.asc(dbString));
                }
            }

        }

    }

}