Schedule1Part1AHelper.java

package com.tradecloud.dto.duties;

import com.tradecloud.domain.duties.DutyUnit;
import com.tradecloud.domain.duties.Schedule1Part1A;
import com.tradecloud.domain.duties.TradeAgreement;
import com.tradecloud.tariffing.domain.Duty;
import com.tradecloud.tariffing.domain.Tariff;
import com.tradecloud.tariffing.domain.UnitOfMeasure;
import org.apache.log4j.Logger;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Map;

public class Schedule1Part1AHelper {

    private static  Logger log = Logger.getLogger(Schedule1Part1AHelper.class);

    public static void setTariffCode(Schedule1Part1A dutySchedule, Tariff tariff, String tradeAgreement, Duty duty) {

        boolean isFreeSADC = tradeAgreement.equalsIgnoreCase("SADC") && duty.getDescription().equalsIgnoreCase("free");
        boolean isFreeEU = tradeAgreement.equalsIgnoreCase("EU") && duty.getDescription().equalsIgnoreCase("free");

        if (!isFreeSADC && !isFreeEU) {
            if (tariff.getDutyUnit().toLowerCase().contains("li") || tariff.getDutyUnit().equalsIgnoreCase("l")) {
                setDutyUnit(dutySchedule, tariff, duty, DutyType.LITRES, isFreeSADC, isFreeEU);
            } else if (tariff.getDutyUnit().toLowerCase().contains("2u")) {
                setDutyUnit(dutySchedule, tariff, duty, DutyType.PAIRS, isFreeSADC, isFreeEU);
            } else if (tariff.getDutyUnit().toLowerCase().contains("kg")) {
                setDutyUnit(dutySchedule, tariff, duty, DutyType.KILOGRAM, isFreeSADC, isFreeEU);
            } else if (duty.getDescription().toLowerCase().contains("free")) {
                setDutyUnit(dutySchedule, tariff, duty, DutyType.FREE, isFreeSADC, isFreeEU);
            } else {
                setDutyRate(dutySchedule, duty, isFreeSADC, isFreeEU);
            }
        } else {
            setSadcAndEuDutyRate(dutySchedule, duty);
        }

        setCalculationMethod(dutySchedule, tariff);
        dutySchedule.setTradeAgreement(TradeAgreement.valueOf(tradeAgreement.toUpperCase()));
        List<Map.Entry<String, Duty>> dutiesAsList = TariffGeneralHelper.getDutiesAsList(tariff);
        Map.Entry<String, Duty> stringDutyEntry = TariffGeneralHelper.getDutyEntry(dutySchedule.getTradeAgreement(),dutiesAsList);
        if(stringDutyEntry!=null) {
            dutySchedule.setDutyDescription(stringDutyEntry.getValue().getDescription());
        }
        TariffGeneralHelper.setBaseTariffCode(dutySchedule, tariff);
    }

    private static void setDutyUnit(Schedule1Part1A dutySchedule, Tariff tariff, Duty duty, DutyType dutyType, boolean isSadc, boolean isEu) {

        if (isSadc || isEu) {
            setSadcAndEuDutyRate(dutySchedule, duty);
        } else {
            if (duty.getUnitOfMeasure().equals(UnitOfMeasure.PERCENT)) {
                setPercentageDutyRate(dutySchedule, duty);
            } else if (duty.getUnitOfMeasure().equals(UnitOfMeasure.ZAR)) {
                setZarDutyRate(dutySchedule, duty, dutyType, tariff);
            }
        }
    }

    private static void setDutyRate(Schedule1Part1A dutySchedule, Duty duty, boolean isSadc, boolean isEu) {

        if (isSadc || isEu) {
            setSadcAndEuDutyRate(dutySchedule, duty);
        } else {
            if (duty.getUnitOfMeasure().equals(UnitOfMeasure.PERCENT)) {
                dutySchedule.getDutyRate().setPercentage(new BigDecimal(duty.getValue()));
                dutySchedule.getDutyRate().setValue(new BigDecimal(0));
            } else if (duty.getUnitOfMeasure().equals(UnitOfMeasure.ZAR)) {
                dutySchedule.getDutyRate().setValue(new BigDecimal(duty.getValue()));
                dutySchedule.getDutyRate().setPercentage(new BigDecimal(0));
            }
        }
    }

    private static void setSadcAndEuDutyRate(Schedule1Part1A dutySchedule, Duty duty) {
        dutySchedule.getDutyRate().setPercentage(new BigDecimal(duty.getValue()));
        dutySchedule.getDutyRate().setValue(new BigDecimal(duty.getValue()));
    }

    private static void setCalculationMethod(Schedule1Part1A dutySchedule, Tariff tariff) {
        String dutyDescription = tariff.getGeneralDuty().getDescription().toLowerCase();
        dutySchedule.setCalculationMethod(TariffGeneralHelper.getCalculationMethod(dutyDescription));
    }

    private static void setPercentageDutyRate(Schedule1Part1A dutySchedule, Duty duty) {
        dutySchedule.getDutyRate().setPercentage(new BigDecimal(duty.getValue()));
        dutySchedule.getDutyRate().setValue(new BigDecimal(0));
    }

    private static void setZarDutyRate(Schedule1Part1A dutySchedule, Duty duty, DutyType dutyType, Tariff tariff) {

        dutySchedule.getDutyRate().setPercentage(new BigDecimal(0));
        String dutyDescription = tariff.getGeneralDuty().getDescription().toLowerCase();

        switch (dutyType) {
            case LITRES:
                handleLitresDutyUnit(dutySchedule, dutyDescription, tariff);
                break;
            case KILOGRAM:
                handleKgDutyUnit(dutySchedule, dutyDescription, tariff);
                break;
            case PAIRS:
                handlePairsDutyUnit(dutySchedule, dutyDescription);
                break;
        }
    }

    private static void handleKgDutyUnit(Schedule1Part1A dutySchedule, String dutyDescription, Tariff tariff) {

        if (dutyDescription.contains("or")) {
            String[] values = dutyDescription.split("or");
            String percent = values[0].split("%")[0];
            String cents = values[1].split("c")[0];

            if (dutyDescription.contains("less")) {
                String[] otherValues = dutyDescription.split("less");
                String otherPercent = otherValues[1].split("%")[0];
                dutySchedule.getDutyRate().getOtherDuty2().setValue(new BigDecimal(otherPercent.trim()));
            }

            dutySchedule.getDutyRate().setPercentage(new BigDecimal(percent));
            dutySchedule.getDutyRate().setValue(new BigDecimal(0));
            dutySchedule.getDutyRate().getOtherDuty1().setValue(new BigDecimal(TariffGeneralHelper.stringToDouble(cents) / 100)
                    .setScale(5, RoundingMode.HALF_DOWN));
            dutySchedule.getDutyRate().getOtherDuty1().setUnit(DutyUnit.MASS_KG);

        } else {
            dutySchedule.getDutyRate().setPercentage(new BigDecimal(0));
            dutySchedule.getDutyRate().setValue(new BigDecimal(0));
            String cents = dutyDescription.split("c")[0];
            dutySchedule.getDutyRate().getOtherDuty1().setValue(new BigDecimal(TariffGeneralHelper.stringToDouble(cents) / 100)
                    .setScale(5, RoundingMode.HALF_DOWN));
            dutySchedule.getDutyRate().getOtherDuty1().setUnit(TariffGeneralHelper.getDutyUnit(dutyDescription, DutyUnit.MASS_KG));

            if (dutyDescription.contains("less") && dutyDescription.contains("with a maximum of")) {
                String[] otherValues = dutyDescription.split("less");
                String otherPercent = otherValues[1].split("%")[0];
                dutySchedule.getDutyRate().getOtherDuty2().setValue(new BigDecimal(otherPercent.trim()));

                String[] otherValues2 = dutyDescription.split("with a maximum of");
                String otherPercent2 = otherValues2[1].split("%")[0];
                dutySchedule.getDutyRate().getOtherDuty3().setValue(new BigDecimal(otherPercent2.trim()));
            } else if (!dutyDescription.contains("less") && dutyDescription.contains("with a maximum of")) {
                String[] otherValues = dutyDescription.split("with a maximum of");
                String otherPercent = otherValues[1].split("%")[0];
                dutySchedule.getDutyRate().getOtherDuty2().setValue(new BigDecimal(otherPercent.trim()));
            }
        }
    }

    private static void handleLitresDutyUnit(Schedule1Part1A dutySchedule, String dutyDescription, Tariff tariff) {
        dutyDescription = dutyDescription.toLowerCase();
        dutySchedule.getDutyRate().setPercentage(new BigDecimal(0));
        dutySchedule.getDutyRate().setValue(new BigDecimal(0));
        String cents = dutyDescription.split("c")[0];
        dutySchedule.getDutyRate().getOtherDuty1().setValue(new BigDecimal(TariffGeneralHelper.stringToDouble(cents) / 100)
                .setScale(5, RoundingMode.HALF_DOWN));
        dutySchedule.getDutyRate().getOtherDuty1().setUnit(TariffGeneralHelper.getDutyUnit(dutyDescription, DutyUnit.VOLUME_L));

        if (!dutyDescription.contains("less") && dutyDescription.contains("with a maximum of")) {
            String[] otherValues = dutyDescription.split("with a maximum of");
            String otherPercent = otherValues[1].split("%")[0];
            dutySchedule.getDutyRate().getOtherDuty2().setValue(new BigDecimal(otherPercent.trim()));
        }
    }

    private static void handlePairsDutyUnit(Schedule1Part1A dutySchedule, String dutyDescription) {

        if (dutyDescription.contains("free")) {
            setFreeDutyRate(dutySchedule);
        } else {
            String[] values = dutyDescription.split("or");
            String percent = null;
            String cents = "0";
            try {
                percent = values[0].split("%")[0];
                cents = values.length > 1 ? values[1].split("c")[0] : cents;
            } catch (ArrayIndexOutOfBoundsException e) {
                log.error("Error parsing dutyDescription: " + dutyDescription);
                e.printStackTrace();
                throw e;
            }

            dutySchedule.getDutyRate().setPercentage(new BigDecimal(percent));
            dutySchedule.getDutyRate().setValue(new BigDecimal(0));
            dutySchedule.getDutyRate().getOtherDuty1().setValue(
                    new BigDecimal(TariffGeneralHelper.stringToDouble(cents) / 100).setScale(5, RoundingMode.HALF_DOWN));
            dutySchedule.getDutyRate().getOtherDuty1().setUnit(DutyUnit.PAIRS);
        }
    }

    private static void setFreeDutyRate(Schedule1Part1A dutySchedule) {
        dutySchedule.getDutyRate().setPercentage(new BigDecimal(0));
        dutySchedule.getDutyRate().setValue(new BigDecimal(0));
    }

}