ItemFieldCopyHelper.java

package com.tradecloud.domain.item;

import com.tradecloud.domain.configuration.ItemsAndOrdersClientConfig;
import com.tradecloud.domain.duties.*;
import com.tradecloud.domain.model.ordermanagement.Order;
import com.tradecloud.domain.model.ordermanagement.SalesOrder;
import org.apache.log4j.Logger;

import java.util.ArrayList;

/**
 *
 */
public class ItemFieldCopyHelper {

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

    public static void copyFromClientConfig(LineItem lineItem, ItemsAndOrdersClientConfig config) {
        lineItem.setUnitType(config.getUnitType());
        lineItem.setPackageType(config.getPackageType());
        lineItem.setVolumeUOM(config.getVolumeUOM());
        lineItem.setWeightUOM(config.getWeightUOM());
    }

    /**
     * Ick logic. Always copy if 'onlyIfNull' is false. If it is true, then copy if field is null.
     *
     * @param onlyIfNull
     * @param field
     * @return
     */
    private static boolean shouldCopy(boolean onlyIfNull, Object field) {
        return !(onlyIfNull && field != null);
    }

    /**
     * Copy fields from the Purchase Order.
     *
     * @param onlyIfNull    only copy in if the field has not already been set.
     * @param lineItem
     * @param purchaseOrder
     */
    public static void copyFromPurchaseOrder(boolean onlyIfNull, LineItem lineItem, Order purchaseOrder) {
        if (shouldCopy(onlyIfNull, lineItem.getOrganisationalUnit())) {
            lineItem.setOrganisationalUnit(purchaseOrder.getOrganisationalUnit());
        }
        if (shouldCopy(onlyIfNull, lineItem.getCurrency())) {
            lineItem.setCurrency(purchaseOrder.getCurrency());
        }
        if (shouldCopy(onlyIfNull, lineItem.getCountryOfOrigin())) {
            lineItem.setCountryOfOrigin(purchaseOrder.getShippingInformation().getCountryOfOrigin());
        }
        if (shouldCopy(onlyIfNull, lineItem.getSupplier())) {
            lineItem.setSupplier(purchaseOrder.getSupplier());
        }
    }

    public static void copyFromSalesOrder(boolean onlyIfNull, LineItem lineItem, SalesOrder salesOrder) {
        if (shouldCopy(onlyIfNull, lineItem.getOrganisationalUnit())) {
            lineItem.setOrganisationalUnit(salesOrder.getOrganisationalUnit());
        }
        if (shouldCopy(onlyIfNull, lineItem.getSaleCurrency())) {
            lineItem.setSaleCurrency(salesOrder.getCurrency());
        }
        if (shouldCopy(onlyIfNull, lineItem.getCurrency())) {
            lineItem.setCurrency(salesOrder.getCurrency());
        }
        if (shouldCopy(onlyIfNull, lineItem.getSupplyCurrency())) {
            lineItem.setSupplyCurrency(salesOrder.getSupplyCurrency());
        }
        if (shouldCopy(onlyIfNull, lineItem.getCountryOfOrigin())) {
            lineItem.setCountryOfOrigin(salesOrder.getShippingInformation().getCountryOfOrigin());
        }
        if (shouldCopy(onlyIfNull, lineItem.getSupplier())) {
            lineItem.setSupplier(salesOrder.getSupplier());
        }
    }

    private static void copyTariffHeading(DutySchedule from, DutySchedule to) {
        TariffHeading fromTariffHeading = from.getTariffHeading();
        TariffHeading toTariffHeading = to.getTariffHeading();
        toTariffHeading.setPart1(fromTariffHeading.getPart1());
        toTariffHeading.setPart2(fromTariffHeading.getPart2());
        toTariffHeading.setPart3(fromTariffHeading.getPart3());
        toTariffHeading.setPart4(fromTariffHeading.getPart4());
        toTariffHeading.setPart5(fromTariffHeading.getPart5());

        to.setValid(from.isValid());
    }

    private static void copyS1P1A(Schedule1Part1A from, Schedule1Part1A to) {
        //if (!to.isTradeAgreementOverridden()) {
        copyTypedDutyRate(from.getDutyRate(), to.getDutyRate());
        copyTariffHeading(from, to);
        to.setCalculationMethod(from.getCalculationMethod());
        to.setTradeAgreement(from.getTradeAgreement());
        to.setTradeAgreementOverridden(from.isTradeAgreementOverridden());
        to.setDutyDescription(from.getDutyDescription());
        to.setSupplementaryQty1(from.getSupplementaryQty1());
        to.setSupplementaryQty2(from.getSupplementaryQty2());
        to.setSupplementaryQty3(from.getSupplementaryQty3());
        to.setVatExemption(from.isVatExemption());
        to.setValid(from.isValid());
        to.setRulesOfOriginAuthNumber(from.getRulesOfOriginAuthNumber());
        if (to.getRulesOfOrigin() != null)
            to.getRulesOfOrigin().clear();
        else
            to.setRulesOfOrigin(new ArrayList<>());
        if (from.getRulesOfOrigin() != null)
            to.getRulesOfOrigin().addAll(from.getRulesOfOrigin());

        if (from.getRulesOfOrigin() != null)
            to.setRulesOfOrigin(new ArrayList<>(from.getRulesOfOrigin()));
    }

    private static void copyS1P2A(Schedule1Part2A from, Schedule1Part2A to) {
        to.setValid(from.isValid());
        copyDutyRate(from.getDutyRate(), to.getDutyRate());
        copyTariffHeading(from, to);
    }

    private static void copyS1P2B(Schedule1Part2B from, Schedule1Part2B to) {
        to.setValid(from.isValid());
        copyTypedDutyRate(from.getDutyRate(), to.getDutyRate());
        copyTariffHeading(from, to);
    }

    private static void copyS2P1(Schedule2Part1 from, Schedule2Part1 to) {
        to.setValid(from.isValid());
        copyTypedDutyRate(from.getDutyRate(), to.getDutyRate());
        copyTariffHeading(from, to);
    }

    private static void copyS2P2(Schedule2Part2 from, Schedule2Part2 to) {
        to.setValid(from.isValid());
        copyTypedDutyRate(from.getDutyRate(), to.getDutyRate());
        copyTariffHeading(from, to);
    }

    private static void copyS1P3E(Schedule1Part3E from, Schedule1Part3E to) {
        to.setValid(from.isValid());
        copyTypedDutyRate(from.getDutyRate(), to.getDutyRate());
        copyTariffHeading(from, to);
        to.setCalculationMethod(from.getCalculationMethod());
    }

    private static void copyS1P7(Schedule1Part7 from, Schedule1Part7 to) {
        to.setValid(from.isValid());
        copyTypedDutyRate(from.getDutyRate(), to.getDutyRate());
        copyTariffHeading(from, to);
        to.setCalculationMethod(from.getCalculationMethod());
    }

    private static void copyS3P1(Schedule3Part1 from, Schedule3Part1 to) {
        to.setValid(from.isValid());
        copyTypedDutyRate(from.getDutyRate(), to.getDutyRate());
        copyTariffHeading(from, to);
        to.setCalculationMethod(from.getCalculationMethod());
        to.setVatExemption(from.isVatExemption());
        to.setRebateCode(from.getRebateCode());
        to.setRebateOptions(from.getRebateOptions());
    }

    private static void copyS4P1(Schedule4Part1 from, Schedule4Part1 to) {
        to.setValid(from.isValid());
        copyTypedDutyRate(from.getDutyRate(), to.getDutyRate());
        copyTariffHeading(from, to);
        to.setCalculationMethod(from.getCalculationMethod());
        to.setVatExemption(from.isVatExemption());
        to.setRebateCode(from.getRebateCode());
        to.setRebateOptions(from.getRebateOptions());
    }

    /**
     * Not sure if this one is necessary. It is for copying fields back into an item
     *
     * @param from
     * @param to
     */
    public static void copyMissingDuties(ItemInterface from, ItemInterface to) {
        if (from.getSchedule1Part1A() != null && to.getSchedule1Part1A() == null) {
            initS1P1A(to);
            copyS1P1A(from.getSchedule1Part1A(), to.getSchedule1Part1A());
        }
        if (from.getSchedule1Part2A() != null && to.getSchedule1Part2A() == null) {
            initS1P2A(to);
            copyS1P2A(from.getSchedule1Part2A(), to.getSchedule1Part2A());
        }
        if (from.getSchedule1Part2B() != null && to.getSchedule1Part2B() == null) {
            initS1P2B(to);
            copyS1P2B(from.getSchedule1Part2B(), to.getSchedule1Part2B());
        }
        if (from.getSchedule2Part1() != null && to.getSchedule2Part1() == null) {
            initS2P1(to);
            copyS2P1(from.getSchedule2Part1(), to.getSchedule2Part1());
        }
        if (from.getSchedule2Part2() != null && to.getSchedule2Part2() == null) {
            initS2P2(to);
            copyS2P2(from.getSchedule2Part2(), to.getSchedule2Part2());
        }
        if (from.getSchedule1Part3E() != null) {
            initS1P3E(to);
            copyS1P3E(from.getSchedule1Part3E(), to.getSchedule1Part3E());
        }
        if (from.getSchedule1Part7() != null) {
            initS1P7(to);
            copyS1P7(from.getSchedule1Part7(), to.getSchedule1Part7());
        }
        if (from.getSchedule3Part1() != null) {
            initS3P1(to);
            copyS3P1(from.getSchedule3Part1(), to.getSchedule3Part1());
        }
        if (from.getSchedule4Part1() != null) {
            initS4P1(to);
            copyS4P1(from.getSchedule4Part1(), to.getSchedule4Part1());
        }
    }

    public static void copyDuties(ItemInterface from, ItemInterface to) {
        if (to == null)
            return;

        if (from.getSchedule1Part1A() != null) {
            initS1P1A(to);
            copyS1P1A(from.getSchedule1Part1A(), to.getSchedule1Part1A());
        }
        if (from.getSchedule1Part2A() != null) {
            initS1P2A(to);
            copyS1P2A(from.getSchedule1Part2A(), to.getSchedule1Part2A());
        }
        if (from.getSchedule1Part2B() != null) {
            initS1P2B(to);
            copyS1P2B(from.getSchedule1Part2B(), to.getSchedule1Part2B());
        }
        if (from.getSchedule2Part1() != null) {
            initS2P1(to);
            copyS2P1(from.getSchedule2Part1(), to.getSchedule2Part1());
        }
        if (from.getSchedule2Part2() != null) {
            initS2P2(to);
            copyS2P2(from.getSchedule2Part2(), to.getSchedule2Part2());
        }
        if (from.getSchedule1Part3E() != null) {
            initS1P3E(to);
            copyS1P3E(from.getSchedule1Part3E(), to.getSchedule1Part3E());
        }
        if (from.getSchedule1Part7() != null) {
            initS1P7(to);
            copyS1P7(from.getSchedule1Part7(), to.getSchedule1Part7());
        }

        if (from.getSchedule3Part1() != null) {
            initS3P1(to);
            copyS3P1(from.getSchedule3Part1(), to.getSchedule3Part1());
        }

        if (from.getSchedule4Part1() != null) {
            initS4P1(to);
            copyS4P1(from.getSchedule4Part1(), to.getSchedule4Part1());
        }
    }

    public static void copyTDN(AbstractItem from, AbstractItem to) {
        if (from.getTariffDeterminationNumber() != null) {
            to.setTariffDeterminationNumber(from.getTariffDeterminationNumber());
        }
    }

    /**
     * Determines whether the tariff heading in the schedule is eligible to be deemed as valid.
     * It delegates to {@code TariffHeading} for this decision and if it is then we set the duty schedule validationDisabled flag to false.
     * If it's not eligible then we set the duty schedule valid flag to false and the validationDisabled flag to true.
     * This method is synchronized in an attempt to rule out any race conditions that may be occuring when the network requests are very slow from
     * the UI to the server (as seen on sndtest08 by Mariesa).  There was some inconsistency with the valid checkbox and when it was being made
     * enabled/disabled.  The problem can't be created locally (so far).
     *
     * @param schedule the schedule whose tariff heading is being checked
     * @throws NullPointerException if schedule is null
     */
    public static synchronized void determineTariffHeadingValidationStatus(DutySchedule schedule) {
        if (schedule.eligibleForValidation()) {
            //log.debug("Schedude (" + schedule.getTariffHeading().getTariffHeading() + ") is eligible for validation");
            schedule.setValidationDisabled(false);
            schedule.setValid(true);
        } else {
            //log.debug("Schedude (" + schedule.getTariffHeading().getTariffHeading() + ") is NOT eligible for validation");
            schedule.setValid(false);
            schedule.setValidationDisabled(true);
        }
    }

    /**
     * Initialises an item's schedules and internal objects to ensure there are no NullPointerExceptions thrown from the UI when attempts are
     * made to access certain inner objects. TODO. There are null checks all the way through the object tree. Surely we can just create
     * the whole schedule if it is needed?
     * This method is called prior to doing a "create order" or "create product" on the UI.
     *
     * @param item a subclass of {@code AbstractItem} whose schedules we need to initialise
     */
    public static void initialiseSchedules(ItemInterface item) {
        initS1P1A(item);
        initS1P2A(item);
        initS1P2B(item);
        initS2P1(item);
        initS2P2(item);
        initS1P3E(item);
        initS3P1(item);
        initS4P1(item);
        initS1P7(item);
    }

    private static void initS1P1A(ItemInterface item) {
        if (item.getSchedule1Part1A() == null) {
            item.setSchedule1Part1A(new Schedule1Part1A());
        }
        initialiseSchedule(item.getSchedule1Part1A());
    }

    private static void initS1P2A(ItemInterface item) {
        if (item.getSchedule1Part2A() == null) {
            item.setSchedule1Part2A(new Schedule1Part2A());
        }
        if (item.getSchedule1Part2A().getDutyRate() == null) {
            item.getSchedule1Part2A().setDutyRate(new DutyRate());
        }
        initialiseSchedule(item.getSchedule1Part2A());
    }

    private static void initS1P2B(ItemInterface item) {
        if (item.getSchedule1Part2B() == null) {
            item.setSchedule1Part2B(new Schedule1Part2B());
        }
        initialiseSchedule(item.getSchedule1Part2B());
    }

    private static void initS2P1(ItemInterface item) {
        if (item.getSchedule2Part1() == null) {
            item.setSchedule2Part1(new Schedule2Part1());
        }
        initialiseSchedule(item.getSchedule2Part1());
    }

    private static void initS2P2(ItemInterface item) {
        if (item.getSchedule2Part2() == null) {
            item.setSchedule2Part2(new Schedule2Part2());
        }
        initialiseSchedule(item.getSchedule2Part2());
    }

    private static void initS1P3E(ItemInterface item) {
        if (item.getSchedule1Part3E() == null) {
            item.setSchedule1Part3E(new Schedule1Part3E());
        }
        initialiseSchedule(item.getSchedule1Part3E());
    }

    private static void initS1P7(ItemInterface item) {
        if (item.getSchedule1Part7() == null) {
            item.setSchedule1Part7(new Schedule1Part7());
        }
        initialiseSchedule(item.getSchedule1Part7());
    }

    private static void initS3P1(ItemInterface item) {
        if (item.getSchedule3Part1() == null) {
            item.setSchedule3Part1(new Schedule3Part1());
        }
        initialiseSchedule(item.getSchedule3Part1());
    }

    private static void initS4P1(ItemInterface item) {
        if (item.getSchedule4Part1() == null) {
            item.setSchedule4Part1(new Schedule4Part1());
        }
        initialiseSchedule(item.getSchedule4Part1());
    }

    /**
     * Handles common functionality for initialising a schedule for the UI.
     *
     * @param schedule the schedule to initialise
     */
    private static void initialiseSchedule(DutySchedule schedule) {
        initialiseOtherDuties(schedule.getDutyRate());
        determineTariffHeadingValidationStatus(schedule);
        if (schedule.getTariffHeading() == null) {
            schedule.setTariffHeading(new TariffHeading());
        }
    }

    /**
     * Initialises the {@code OtherDuty} fields in a duty rate.
     *
     * @param dutyRate the duty rate whose other duty fields need to be initialised
     */
    private static void initialiseOtherDuties(AbstractDutyRate dutyRate) {
        if (dutyRate.getOtherDuty1() == null) {
            dutyRate.setOtherDuty1(new OtherDuty());
        }
        if (dutyRate.getOtherDuty2() == null) {
            dutyRate.setOtherDuty2(new OtherDuty());
        }
        if (dutyRate.getOtherDuty3() == null) {
            dutyRate.setOtherDuty3(new OtherDuty());
        }
    }

    private static void copyOtherDuty(OtherDuty from, OtherDuty to) {
        to.setAdditionalValue(from.getAdditionalValue());
        to.setProof(from.getProof());
        to.setUnit(from.getUnit());
        to.setValue(from.getValue());
    }

    private static void copyTypedDutyRate(TypedDutyRate from, TypedDutyRate to) {
        to.setType(from.getType());
        to.setPercentage(from.getPercentage());
        to.setValue(from.getValue());

        ItemFieldCopyHelper.copyOtherDuty(from.getOtherDuty1(), to.getOtherDuty1());
        ItemFieldCopyHelper.copyOtherDuty(from.getOtherDuty2(), to.getOtherDuty2());
        ItemFieldCopyHelper.copyOtherDuty(from.getOtherDuty3(), to.getOtherDuty3());
    }

    private static void copyDutyRate(DutyRate from, DutyRate to) {

        to.setValue(from.getValue());

        ItemFieldCopyHelper.copyOtherDuty(from.getOtherDuty1(), to.getOtherDuty1());
        ItemFieldCopyHelper.copyOtherDuty(from.getOtherDuty2(), to.getOtherDuty2());
        ItemFieldCopyHelper.copyOtherDuty(from.getOtherDuty3(), to.getOtherDuty3());

        /*
        from.getOtherDuty1().setAdditionalValue(to.getOtherDuty1().getAdditionalValue());
        from.getOtherDuty1().setProof(to.getOtherDuty1().getProof());
        from.getOtherDuty1().setUnit(to.getOtherDuty1().getUnit());
        from.getOtherDuty1().setValue(to.getOtherDuty1().getValue());

        from.getOtherDuty2().setAdditionalValue(to.getOtherDuty2().getAdditionalValue());
        from.getOtherDuty2().updateTariffInformationsetProof(to.getOtherDuty2().getProof());
        from.getOtherDuty2().setUnit(to.getOtherDuty2().getUnit());
        from.getOtherDuty2().setValue(to.getOtherDuty2().getValue());

        from.getOtherDuty3().setAdditionalValue(to.getOtherDuty3().getAdditionalValue());
        from.getOtherDuty3().setProof(to.getOtherDuty3().getProof());
        from.getOtherDuty3().setUnit(to.getOtherDuty3().getUnit());
        from.getOtherDuty3().setValue(to.getOtherDuty3().getValue());
        */
    }

    public static void copySABS(AbstractItem from, AbstractItem to) {
        if (from.getSabsTariff() != null) {
            to.setSabsTariff(from.getSabsTariff());
        }
        if (from.getSabsTariff2() != null) {
            to.setSabsTariff2(from.getSabsTariff2());
        }
    }

    public static void copyVDN(AbstractItem from, AbstractItem to) {
        if (from.getValueDeterminationNumber() != null) {
            to.setValueDeterminationNumber(new ValueDeterminationNumber(from.getValueDeterminationNumber()));
        }
    }
}