RuleProcessor.java

package com.tradecloud.repository.workload.impl;

import com.tradecloud.domain.base.utils.DateUtils;
import com.tradecloud.domain.workload.DateFilter;
import com.tradecloud.domain.workload.DateFormulaOperator;
import com.tradecloud.domain.workload.WorkLoadAllocation;
import com.tradecloud.domain.workload.WorkLoadRule;
import org.hibernate.Session;
import org.hibernate.query.NativeQuery;
import org.hibernate.transform.Transformers;
import org.hibernate.type.StandardBasicTypes;

import java.util.*;

public abstract class RuleProcessor  {

private Session session;

    public RuleProcessor(Session session) {
        this.session = session;
    }

    private static final Map<DateFormulaOperator, String> OPERATOR_MAP = Map.of(
            DateFormulaOperator.EQUAL_TO, "=    date(:dateV)",
            DateFormulaOperator.LESS_THAN, "< date(:dateV)",
            DateFormulaOperator.GREATER_THAN, "> date(:dateV)",
            DateFormulaOperator.GREATER_THAN_OR_EQUAL_TO, ">= date(:dateV)",
            DateFormulaOperator.LESS_THAN_OR_EQUAL_TO, "<= date(:dateV)"
    );

    public List<Map<String, String>> findAllByRule(WorkLoadRule rule) {
        String baseTable = getBaseTable();
        String joinClause = getJoinClause(rule);
        // Get the column name for filtering
        String dateColumn = getDateColumn(rule.getDateFilter());

        if (dateColumn == null) {
            return Collections.emptyList();
        }
        // Construct the query
        String sql = String.format(
                getQuery(),
                dateFilterStringMap().get(rule.getPriorityDateFilter()) ,baseTable, joinClause, dateColumn
        );

        sql = addDateFilter(rule, sql);
        sql += getExcludeFilter();

        sql = filterByRuleAttribute(rule, sql);
        sql = addServiceProvideFilter(rule, sql);
        sql = addPaymentTermFilter(rule, sql);
        if(rule.getModeOfTransport()!=null) {
            sql = addShippingModeFilter(rule, sql);
        }
        if(rule.getOrderStates()!=null && !rule.getOrderStates().isEmpty()){
            sql = addOrderStatesFilter(rule, sql);
        }
        // Execute the query
        NativeQuery nativeQuery = session
                .createNativeQuery(sql);
        Date formulaDate = DateUtils.getStartOfDay(DateUtils.addDays(new Date(), rule.getDateFormulaValue()));

        nativeQuery.setParameter("dateV", formulaDate);
        if(rule.getServiceProviderType()!=null && rule.getServiceProvider()!=null){
            nativeQuery = nativeQuery.setParameter("sp_id", rule.getServiceProvider().getId());
        }

        if(rule.getModeOfTransport()!=null) {
            nativeQuery.setParameter("shippingMode",rule.getModeOfTransport().name());
        }
        if(rule.getOrderStates()!=null && !rule.getOrderStates().isEmpty()){
            nativeQuery.setParameterList("orderStates",rule.getOrderStates().stream().map(orderState -> orderState.name()).toList());
        }

        if(rule.getPaymentTerm()!=null){
            nativeQuery.setParameter("paymentTerm",rule.getPaymentTerm().getCode());
        }

        return nativeQuery
                .addScalar("id", StandardBasicTypes.STRING)
                .addScalar("reference", StandardBasicTypes.STRING)
                .addScalar("supplier", StandardBasicTypes.STRING)
                .addScalar("number", StandardBasicTypes.STRING)
                .addScalar("ruledate", StandardBasicTypes.STRING)
                .addScalar("state", StandardBasicTypes.STRING)
                .setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP)
                .list();
    }

    protected abstract String addPaymentTermFilter(WorkLoadRule rule, String sql);

    protected abstract String addOrderStatesFilter(WorkLoadRule rule, String sql);

    private String getDateColumn(DateFilter dateFilter) {
        String dateColumn = Optional.ofNullable(dateFilterStringMap().get(dateFilter))
                .filter(s -> !s.isBlank())
                .map(s -> String.format("date(%s)", s))
                .orElseThrow(() -> new IllegalArgumentException(
                        "No date column mapping found for filter: " + dateFilter
                ));
        return dateColumn;
    }

    protected abstract String addShippingModeFilter(WorkLoadRule rule, String sql);

    protected abstract String getQuery();

    protected abstract String getExcludeFilter();

    protected abstract String getBaseTable();

    protected abstract Map<DateFilter, String> dateFilterStringMap();

    protected abstract String addServiceProvideFilter(WorkLoadRule rule, String sql);

    protected abstract String filterByRuleAttribute(WorkLoadRule rule, String sql);

    private String addDateFilter(WorkLoadRule workLoadRule, String sql) {
        String operator = OPERATOR_MAP.get(workLoadRule.getDateFormulaOperator());
        if (operator == null) {
            throw new IllegalStateException("Cannot process date formula operation: " + workLoadRule.getDateFormulaOperator());
        }
        return sql + operator;
    }

    protected abstract String getJoinClause(WorkLoadRule rule);

    public List<Map<String, String>> findPriorityAttr(WorkLoadAllocation workLoadAllocation) {
        WorkLoadRule workLoadRule = workLoadAllocation.getWorkLoadRule();
        String sql = getPriorityFieldsSql(workLoadRule);
        NativeQuery nativeQuery = session
                .createNativeQuery(String.format(sql, getDateColumn(workLoadRule.getPriorityDateFilter())));
        nativeQuery.setParameter("entityId", workLoadAllocation.getEntityId());

        return nativeQuery
                .addScalar("priorityDate", StandardBasicTypes.STRING)
                .setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP)
                .list();

    }

    protected abstract String getPriorityFieldsSql(WorkLoadRule rule);

}