Example usage for java.math BigDecimal stripTrailingZeros

List of usage examples for java.math BigDecimal stripTrailingZeros

Introduction

In this page you can find the example usage for java.math BigDecimal stripTrailingZeros.

Prototype

public BigDecimal stripTrailingZeros() 

Source Link

Document

Returns a BigDecimal which is numerically equal to this one but with any trailing zeros removed from the representation.

Usage

From source file:com.stratio.cassandra.index.schema.ColumnMapperBigDecimal.java

/** {@inheritDoc} */
@Override/*from   ww  w  .  j  ava2 s.c  om*/
public String indexValue(String name, Object value) {

    // Check not null
    if (value == null) {
        return null;
    }

    // Parse big decimal
    String svalue = value.toString();
    BigDecimal bd;
    try {
        bd = new BigDecimal(value.toString());
    } catch (NumberFormatException e) {
        String message = String.format("Field %s requires a base 10 decimal, but found \"%s\"", name, svalue);
        throw new IllegalArgumentException(message);
    }

    // Split integer and decimal part
    bd = bd.stripTrailingZeros();
    String[] parts = bd.toPlainString().split("\\.");
    String integerPart = parts[0];
    String decimalPart = parts.length == 1 ? "0" : parts[1];

    if (integerPart.replaceFirst("-", "").length() > integerDigits) {
        throw new IllegalArgumentException("Too much digits in integer part");
    }
    if (decimalPart.length() > decimalDigits) {
        throw new IllegalArgumentException("Too much digits in decimal part");
    }

    BigDecimal complemented = bd.add(complement);
    String bds[] = complemented.toString().split("\\.");
    integerPart = bds[0];
    decimalPart = bds.length == 2 ? bds[1] : "0";
    integerPart = StringUtils.leftPad(integerPart, integerDigits + 1, '0');

    return integerPart + "." + decimalPart;
}

From source file:eu.europa.ec.fisheries.uvms.rules.service.business.AbstractFact.java

public int getNumberOfDecimalPlaces(BigDecimal bigDecimal) {
    String string = bigDecimal.stripTrailingZeros().toPlainString();
    int index = string.indexOf('.');
    return index < 0 ? 0 : string.length() - index - 1;
}

From source file:eu.europa.ec.fisheries.uvms.rules.service.business.AbstractFact.java

private boolean isIntegerValue(BigDecimal bigDecimal) {
    if (bigDecimal == null) {
        return false;
    }/*from   w  ww .j  av  a2s. c  o m*/

    if (bigDecimal.signum() == 0 || bigDecimal.scale() <= 0 || bigDecimal.stripTrailingZeros().scale() <= 0) {
        return true;
    } else {
        return false;
    }

}

From source file:org.apache.calcite.runtime.SqlFunctions.java

/** SQL <code>=</code> operator applied to BigDecimal values (neither may be
 * null). */// w w w  .j ava2 s.  c  o  m
public static boolean eq(BigDecimal b0, BigDecimal b1) {
    return b0.stripTrailingZeros().equals(b1.stripTrailingZeros());
}

From source file:org.apache.hadoop.hive.serde2.io.BigDecimalWritable.java

public void set(BigDecimal value) {
    value = value.stripTrailingZeros();
    if (value.compareTo(BigDecimal.ZERO) == 0) {
        // Special case for 0, because java doesn't strip zeros correctly on that number.
        value = BigDecimal.ZERO;/*from  w  w  w .  j  a  v a 2  s .  c om*/
    }
    set(value.unscaledValue().toByteArray(), value.scale());
}

From source file:org.apache.sqoop.mapreduce.db.TextSplitter.java

/**
 * Return the string encoded in a BigDecimal.
 * Repeatedly multiply the input value by 65536; the integer portion after
 * such a multiplication represents a single character in base 65536.
 * Convert that back into a char and create a string out of these until we
 * have no data left.//from   w  ww .  j  a  va 2s  .  c o  m
 */
public String bigDecimalToString(BigDecimal bd) {
    BigDecimal cur = bd.stripTrailingZeros();
    StringBuilder sb = new StringBuilder();

    for (int numConverted = 0; numConverted < MAX_CHARS; numConverted++) {
        cur = cur.multiply(ONE_PLACE);
        int curCodePoint = cur.intValue();
        if (0 == curCodePoint) {
            break;
        }

        cur = cur.subtract(new BigDecimal(curCodePoint));
        sb.append(Character.toChars(curCodePoint));
    }

    return sb.toString();
}

From source file:org.cryptomath.util.NumberUtil.java

public static BigDecimal truncate(final String text, final int pTimes) {
    BigDecimal bigDecimal = new BigDecimal(text);
    if (bigDecimal.scale() > pTimes) {
        bigDecimal = new BigDecimal(text).setScale(pTimes, RoundingMode.HALF_UP);
    }/*  w  w w .  ja  va  2 s.  c  o  m*/
    return bigDecimal.stripTrailingZeros();
}

From source file:org.kuali.kfs.module.purap.service.impl.PurapAccountingServiceImpl.java

/**
 * @see org.kuali.kfs.module.purap.service.PurapAccountingService#generateAccountDistributionForProration(java.util.List,
 *      org.kuali.rice.core.api.util.type.KualiDecimal, java.lang.Integer)
 *///  ww  w  . j a v  a  2s. c o  m
@Override
public List<PurApAccountingLine> generateAccountDistributionForProration(List<SourceAccountingLine> accounts,
        KualiDecimal totalAmount, Integer percentScale, Class clazz) {
    String methodName = "generateAccountDistributionForProration()";
    if (LOG.isDebugEnabled()) {
        LOG.debug(methodName + " started");
    }
    List<PurApAccountingLine> newAccounts = new ArrayList();

    if (totalAmount.isZero()) {
        throwRuntimeException(methodName,
                "Purchasing/Accounts Payable account distribution for proration does not allow zero dollar total.");
    }

    BigDecimal percentTotal = BigDecimal.ZERO;
    BigDecimal totalAmountBigDecimal = totalAmount.bigDecimalValue();
    for (SourceAccountingLine accountingLine : accounts) {
        KualiDecimal amt = KualiDecimal.ZERO;
        if (ObjectUtils.isNotNull(accountingLine.getAmount())) {
            amt = accountingLine.getAmount();
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug(methodName + " " + accountingLine.getAccountNumber() + " " + amt + "/"
                    + totalAmountBigDecimal);
        }
        BigDecimal pct = amt.bigDecimalValue().divide(totalAmountBigDecimal, percentScale,
                BIG_DECIMAL_ROUNDING_MODE);
        pct = pct.stripTrailingZeros().multiply(ONE_HUNDRED);

        if (LOG.isDebugEnabled()) {
            LOG.debug(methodName + " pct = " + pct + "  (trailing zeros removed)");
        }

        BigDecimal lowestPossible = this.getLowestPossibleRoundUpNumber();
        if (lowestPossible.compareTo(pct) <= 0) {
            PurApAccountingLine newAccountingLine;
            newAccountingLine = null;

            try {
                newAccountingLine = (PurApAccountingLine) clazz.newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }

            ObjectPopulationUtils.populateFromBaseClass(AccountingLineBase.class, accountingLine,
                    newAccountingLine, PurapConstants.KNOWN_UNCOPYABLE_FIELDS);
            newAccountingLine.setAccountLinePercent(pct);
            if (LOG.isDebugEnabled()) {
                LOG.debug(methodName + " adding " + newAccountingLine.getAccountLinePercent());
            }
            newAccounts.add(newAccountingLine);
            percentTotal = percentTotal.add(newAccountingLine.getAccountLinePercent());
            if (LOG.isDebugEnabled()) {
                LOG.debug(methodName + " total = " + percentTotal);
            }
        }
    }

    if ((percentTotal.compareTo(BigDecimal.ZERO)) == 0) {
        /*
         * This means there are so many accounts or so strange a distribution that we can't round properly... not sure of viable
         * solution
         */
        throwRuntimeException(methodName, "Can't round properly due to number of accounts");
    }

    // Now deal with rounding
    if ((ONE_HUNDRED.compareTo(percentTotal)) < 0) {
        /*
         * The total percent is greater than one hundred Here we find the account that occurs latest in our list with a percent
         * that is higher than the difference and we subtract off the difference
         */
        BigDecimal difference = percentTotal.subtract(ONE_HUNDRED);
        if (LOG.isDebugEnabled()) {
            LOG.debug(methodName + " Rounding up by " + difference);
        }

        boolean foundAccountToUse = false;
        int currentNbr = newAccounts.size() - 1;
        while (currentNbr >= 0) {
            PurApAccountingLine potentialSlushAccount = newAccounts.get(currentNbr);

            BigDecimal linePercent = BigDecimal.ZERO;
            if (ObjectUtils.isNotNull(potentialSlushAccount.getAccountLinePercent())) {
                linePercent = potentialSlushAccount.getAccountLinePercent();
            }

            if ((difference.compareTo(linePercent)) < 0) {
                // the difference amount is less than the current accounts percent... use this account
                // the 'potentialSlushAccount' technically is now the true 'Slush Account'
                potentialSlushAccount.setAccountLinePercent(linePercent.subtract(difference).movePointLeft(2)
                        .stripTrailingZeros().movePointRight(2));
                foundAccountToUse = true;
                break;
            }
            currentNbr--;
        }

        if (!foundAccountToUse) {
            /*
             * We could not find any account in our list where the percent of that account was greater than that of the
             * difference... doing so on just any account could result in a negative percent value
             */
            throwRuntimeException(methodName, "Can't round properly due to math calculation error");
        }

    } else if ((ONE_HUNDRED.compareTo(percentTotal)) > 0) {
        /*
         * The total percent is less than one hundred Here we find the last account in our list and add the remaining required
         * percent to its already calculated percent
         */
        BigDecimal difference = ONE_HUNDRED.subtract(percentTotal);
        if (LOG.isDebugEnabled()) {
            LOG.debug(methodName + " Rounding down by " + difference);
        }
        PurApAccountingLine slushAccount = newAccounts.get(newAccounts.size() - 1);

        BigDecimal slushLinePercent = BigDecimal.ZERO;
        if (ObjectUtils.isNotNull(slushAccount.getAccountLinePercent())) {
            slushLinePercent = slushAccount.getAccountLinePercent();
        }

        slushAccount.setAccountLinePercent(
                slushLinePercent.add(difference).movePointLeft(2).stripTrailingZeros().movePointRight(2));
    }
    if (LOG.isDebugEnabled()) {
        LOG.debug(methodName + " ended");
    }
    return newAccounts;
}

From source file:org.kuali.kpme.tklm.leave.payout.service.LeavePayoutServiceImpl.java

@Override
public LeavePayout initializePayout(String principalId, String accrualCategoryRule, BigDecimal accruedBalance,
        LocalDate effectiveDate) {
    //Initially, principals may be allowed to edit the transfer amount when prompted to submit this balance transfer, however,
    //a base transfer amount together with a forfeited amount is calculated to bring the balance back to its limit in accordance
    //with transfer limits.
    LeavePayout leavePayout = null;/*from www .ja v  a  2s . c o  m*/
    AccrualCategoryRule accrualRule = HrServiceLocator.getAccrualCategoryRuleService()
            .getAccrualCategoryRule(accrualCategoryRule);

    if (ObjectUtils.isNotNull(accrualRule) && ObjectUtils.isNotNull(accruedBalance)) {
        leavePayout = new LeavePayout();
        //Leave summary is not a requirement, per se, but the information it contains is.
        //The only thing that is obtained from leave summary is the accrued balance of the leave summary row matching the
        //passed accrualCategoryRules accrual category.
        //These two objects are essential to balance transfers triggered when the employee submits their leave calendar for approval.
        //Neither of these objects should be null, otherwise this method could not have been called.
        AccrualCategory fromAccrualCategory = HrServiceLocator.getAccrualCategoryService()
                .getAccrualCategory(accrualRule.getLmAccrualCategoryId());
        BigDecimal fullTimeEngagement = HrServiceLocator.getJobService()
                .getFteSumForAllActiveLeaveEligibleJobs(principalId, effectiveDate);

        // AccrualRule.maxBalance == null -> no balance limit. No balance limit -> no accrual triggered transfer / payout / lose.
        // execution point should not be here if max balance on accrualRule is null, unless there exists an employee override.
        BigDecimal maxBalance = accrualRule.getMaxBalance();
        BigDecimal adjustedMaxBalance = maxBalance.multiply(fullTimeEngagement).setScale(2);

        BigDecimal maxPayoutAmount = null;
        BigDecimal adjustedMaxPayoutAmount = null;
        if (ObjectUtils.isNotNull(accrualRule.getMaxPayoutAmount())) {
            maxPayoutAmount = new BigDecimal(accrualRule.getMaxPayoutAmount());
            adjustedMaxPayoutAmount = maxPayoutAmount.multiply(fullTimeEngagement).setScale(2);
        } else {
            // no limit on transfer amount
            maxPayoutAmount = new BigDecimal(Long.MAX_VALUE);
            adjustedMaxPayoutAmount = maxPayoutAmount;
        }

        BigDecimal maxCarryOver = null;
        BigDecimal adjustedMaxCarryOver = null;
        if (ObjectUtils.isNotNull(accrualRule.getMaxCarryOver())) {
            maxCarryOver = new BigDecimal(accrualRule.getMaxCarryOver());
            adjustedMaxCarryOver = maxCarryOver.multiply(fullTimeEngagement).setScale(2);
        } else {
            //no limit to carry over.
            maxCarryOver = new BigDecimal(Long.MAX_VALUE);
            adjustedMaxCarryOver = maxCarryOver;
        }

        EmployeeOverrideContract maxBalanceOverride = LmServiceLocator.getEmployeeOverrideService()
                .getEmployeeOverride(principalId, fromAccrualCategory.getLeavePlan(),
                        fromAccrualCategory.getAccrualCategory(), "MB", effectiveDate);
        EmployeeOverrideContract maxPayoutAmountOverride = LmServiceLocator.getEmployeeOverrideService()
                .getEmployeeOverride(principalId, fromAccrualCategory.getLeavePlan(),
                        fromAccrualCategory.getAccrualCategory(), "MPA", effectiveDate);
        EmployeeOverrideContract maxAnnualCarryOverOverride = LmServiceLocator.getEmployeeOverrideService()
                .getEmployeeOverride(principalId, fromAccrualCategory.getLeavePlan(),
                        fromAccrualCategory.getAccrualCategory(), "MAC", effectiveDate);
        //Do not pro-rate override values for FTE.
        if (maxBalanceOverride != null)
            adjustedMaxBalance = new BigDecimal(maxBalanceOverride.getOverrideValue());
        if (maxPayoutAmountOverride != null)
            adjustedMaxPayoutAmount = new BigDecimal(maxPayoutAmountOverride.getOverrideValue());
        if (maxAnnualCarryOverOverride != null)
            adjustedMaxCarryOver = new BigDecimal(maxAnnualCarryOverOverride.getOverrideValue());

        BigDecimal transferAmount = accruedBalance.subtract(adjustedMaxBalance);
        if (transferAmount.compareTo(adjustedMaxPayoutAmount) > 0) {
            //there's forfeiture.
            //bring transfer amount down to the adjusted maximum transfer amount, and place excess in forfeiture.
            //accruedBalance - adjustedMaxPayoutAmount - adjustedMaxBalance = forfeiture.
            //transferAmount = accruedBalance - adjustedMaxBalance; forfeiture = transferAmount - adjustedMaxPayoutAmount.
            BigDecimal forfeiture = transferAmount.subtract(adjustedMaxPayoutAmount).setScale(2);
            forfeiture = forfeiture.stripTrailingZeros();
            leavePayout.setForfeitedAmount(forfeiture);
            leavePayout.setPayoutAmount(adjustedMaxPayoutAmount);
        } else {
            leavePayout.setPayoutAmount(transferAmount);
            leavePayout.setForfeitedAmount(BigDecimal.ZERO);
        }

        assert (adjustedMaxBalance.compareTo(accruedBalance
                .subtract(leavePayout.getPayoutAmount().add(leavePayout.getForfeitedAmount()))) == 0);

        // Max Carry Over logic for Year End transfers.
        if (StringUtils.equals(accrualRule.getMaxBalanceActionFrequency(),
                HrConstants.MAX_BAL_ACTION_FREQ.YEAR_END)) {
            if (ObjectUtils.isNotNull(maxCarryOver)) {

                if (ObjectUtils.isNull(adjustedMaxCarryOver))
                    adjustedMaxCarryOver = maxCarryOver.multiply(fullTimeEngagement).setScale(2);
                //otherwise, adjustedMaxCarryOver has an employee override value, which trumps accrual rule defined MAC.
                //At this point, transfer amount and forfeiture have been set so that the new accrued balance will be the
                //adjusted max balance, so this amount is used to check against carry over.
                if (adjustedMaxBalance.compareTo(adjustedMaxCarryOver) > 0) {
                    BigDecimal carryOverDiff = adjustedMaxBalance.subtract(adjustedMaxCarryOver);

                    if (StringUtils.equals(accrualRule.getActionAtMaxBalance(),
                            HrConstants.ACTION_AT_MAX_BALANCE.LOSE)) {
                        //add carry over excess to forfeiture.
                        leavePayout.setForfeitedAmount(leavePayout.getForfeitedAmount().add(carryOverDiff));
                    } else {
                        //maximize the transfer amount.
                        BigDecimal potentialPayoutAmount = leavePayout.getPayoutAmount().add(carryOverDiff);

                        //Can this entire amount be added to the transfer amount??
                        if (potentialPayoutAmount.compareTo(adjustedMaxPayoutAmount) <= 0) {
                            //yes
                            leavePayout.setPayoutAmount(leavePayout.getPayoutAmount().add(carryOverDiff));
                        } else {
                            //no
                            BigDecimal carryOverExcess = potentialPayoutAmount
                                    .subtract(adjustedMaxPayoutAmount);
                            //move excess to forfeiture
                            leavePayout
                                    .setForfeitedAmount(leavePayout.getForfeitedAmount().add(carryOverExcess));
                            //the remainder (if any) can be added to the transfer amount ( unless action is LOSE ).
                            leavePayout.setPayoutAmount(
                                    leavePayout.getPayoutAmount().add(carryOverDiff.subtract(carryOverExcess)));

                            assert (adjustedMaxCarryOver.compareTo(accruedBalance.subtract(
                                    leavePayout.getPayoutAmount().add(leavePayout.getForfeitedAmount()))) == 0);
                        }
                    }
                }
                //otherwise, given balance will be at or under the max annual carry over.
            }
        }

        leavePayout.setEffectiveLocalDate(effectiveDate);
        leavePayout.setAccrualCategoryRule(accrualCategoryRule);
        leavePayout.setFromAccrualCategory(fromAccrualCategory.getAccrualCategory());
        leavePayout.setPrincipalId(principalId);
        leavePayout.setUserPrincipalId(HrContext.getPrincipalId());
        leavePayout.setEarnCode(accrualRule.getMaxPayoutEarnCode());

    }
    return leavePayout;
}

From source file:org.kuali.kpme.tklm.leave.transfer.service.BalanceTransferServiceImpl.java

@Override
public BalanceTransfer initializeTransfer(String principalId, String accrualCategoryRule,
        BigDecimal accruedBalance, LocalDate effectiveDate) {
    //Initially, principals may be allowed to edit the transfer amount when prompted to submit this balance transfer, however,
    //a base transfer amount together with a forfeited amount is calculated to bring the balance back to its limit in accordance
    //with transfer limits. This "default" transfer object is used to adjust forfeiture when the user changes the transfer amount.
    BalanceTransfer bt = null;/*from   w  w w.j  a va2 s.  co m*/
    AccrualCategoryRule accrualRule = HrServiceLocator.getAccrualCategoryRuleService()
            .getAccrualCategoryRule(accrualCategoryRule);

    if (ObjectUtils.isNotNull(accrualRule) && ObjectUtils.isNotNull(accruedBalance)) {
        bt = new BalanceTransfer();
        //These two objects are essential to balance transfers triggered when the employee submits their leave calendar for approval.
        //Neither of these objects should be null, otherwise this method could not have been called.
        AccrualCategory fromAccrualCategory = HrServiceLocator.getAccrualCategoryService()
                .getAccrualCategory(accrualRule.getLmAccrualCategoryId());
        AccrualCategory toAccrualCategory = HrServiceLocator.getAccrualCategoryService()
                .getAccrualCategory(accrualRule.getMaxBalanceTransferToAccrualCategory(), effectiveDate);
        BigDecimal fullTimeEngagement = HrServiceLocator.getJobService()
                .getFteSumForAllActiveLeaveEligibleJobs(principalId, effectiveDate);

        BigDecimal transferConversionFactor = null;
        if (ObjectUtils.isNotNull(accrualRule.getMaxBalanceTransferConversionFactor()))
            transferConversionFactor = accrualRule.getMaxBalanceTransferConversionFactor();

        // AccrualRule.maxBalance == null -> no balance limit. No balance limit -> no accrual triggered transfer / payout / lose.
        // execution point should not be here if max balance on accrualRule is null, unless there exists an employee override.
        BigDecimal maxBalance = accrualRule.getMaxBalance();
        BigDecimal adjustedMaxBalance = maxBalance.multiply(fullTimeEngagement).setScale(2);

        BigDecimal maxTransferAmount = null;
        BigDecimal adjustedMaxTransferAmount = null;
        if (ObjectUtils.isNotNull(accrualRule.getMaxTransferAmount())) {
            maxTransferAmount = new BigDecimal(accrualRule.getMaxTransferAmount());
            adjustedMaxTransferAmount = maxTransferAmount.multiply(fullTimeEngagement).setScale(2);
        } else {
            // no limit on transfer amount
            maxTransferAmount = new BigDecimal(Long.MAX_VALUE);
            adjustedMaxTransferAmount = maxTransferAmount;
        }

        BigDecimal maxCarryOver = null;
        BigDecimal adjustedMaxCarryOver = null;
        if (ObjectUtils.isNotNull(accrualRule.getMaxCarryOver())) {
            maxCarryOver = new BigDecimal(accrualRule.getMaxCarryOver());
            adjustedMaxCarryOver = maxCarryOver.multiply(fullTimeEngagement).setScale(2);
        } else {
            //no limit to carry over.
            maxCarryOver = new BigDecimal(Long.MAX_VALUE);
            adjustedMaxCarryOver = maxCarryOver;
        }

        List<? extends EmployeeOverrideContract> overrides = LmServiceLocator.getEmployeeOverrideService()
                .getEmployeeOverrides(principalId, effectiveDate);
        for (EmployeeOverrideContract override : overrides) {
            if (StringUtils.equals(override.getAccrualCategory(), fromAccrualCategory.getAccrualCategory())) {
                //Do not pro-rate override values for FTE.
                if (StringUtils.equals(override.getOverrideType(), "MB"))
                    adjustedMaxBalance = new BigDecimal(override.getOverrideValue());
                if (StringUtils.equals(override.getOverrideType(), "MTA"))
                    adjustedMaxTransferAmount = new BigDecimal(override.getOverrideValue());
                if (StringUtils.equals(override.getOverrideType(), "MAC"))
                    adjustedMaxCarryOver = new BigDecimal(override.getOverrideValue());
            }
        }

        BigDecimal transferAmount = accruedBalance.subtract(adjustedMaxBalance);
        if (StringUtils.equals(accrualRule.getActionAtMaxBalance(), HrConstants.ACTION_AT_MAX_BALANCE.LOSE)) {
            //Move all time in excess of employee's fte adjusted max balance to forfeiture.
            bt.setForfeitedAmount(transferAmount);
            //There is no transfer to another accrual category.
            bt.setTransferAmount(BigDecimal.ZERO);
            bt.setAmountTransferred(BigDecimal.ZERO);
            // to accrual category is a required field on maintenance document. Set as from accrual category
            // to remove validation errors when routing, approving, etc.
            bt.setToAccrualCategory(fromAccrualCategory.getAccrualCategory());
        } else {
            // ACTION_AT_MAX_BALANCE = TRANSFER
            bt.setToAccrualCategory(toAccrualCategory.getAccrualCategory());
            if (transferAmount.compareTo(adjustedMaxTransferAmount) > 0) {
                //there's forfeiture.
                //bring transfer amount down to the adjusted maximum transfer amount, and place excess in forfeiture.
                //accruedBalance - adjustedMaxTransferAmount - adjustedMaxBalance = forfeiture.
                //transferAmount = accruedBalance - adjustedMaxBalance; forfeiture = transferAmount - adjustedMaxTransferAmount.
                BigDecimal forfeiture = transferAmount.subtract(adjustedMaxTransferAmount).setScale(2);
                forfeiture = forfeiture.stripTrailingZeros();
                bt.setForfeitedAmount(forfeiture);
                bt.setTransferAmount(adjustedMaxTransferAmount);
            } else {
                bt.setTransferAmount(transferAmount);
                bt.setForfeitedAmount(BigDecimal.ZERO);
            }
        }

        //assert(adjustedMaxBalance.compareTo(accruedBalance.subtract(bt.getTransferAmount().add(bt.getForfeitedAmount()))) == 0);

        // Max Carry Over logic for Year End transfers.
        if (StringUtils.equals(accrualRule.getMaxBalanceActionFrequency(),
                HrConstants.MAX_BAL_ACTION_FREQ.YEAR_END)) {

            //At this point, transfer amount and forfeiture have been set so that the new accrued balance will be the
            //adjusted max balance, so this amount is used to check against carry over.
            if (adjustedMaxBalance.compareTo(adjustedMaxCarryOver) > 0) {
                BigDecimal carryOverDiff = adjustedMaxBalance.subtract(adjustedMaxCarryOver);

                if (StringUtils.equals(accrualRule.getActionAtMaxBalance(),
                        HrConstants.ACTION_AT_MAX_BALANCE.LOSE)) {
                    //add carry over excess to forfeiture.
                    bt.setForfeitedAmount(bt.getForfeitedAmount().add(carryOverDiff));
                } else {
                    //maximize the transfer amount.
                    BigDecimal potentialTransferAmount = bt.getTransferAmount().add(carryOverDiff);

                    //Can this amount be added to the transfer amount without exceeding adjusted max transfer amount??
                    if (potentialTransferAmount.compareTo(adjustedMaxTransferAmount) <= 0) {
                        //yes
                        bt.setTransferAmount(bt.getTransferAmount().add(carryOverDiff));
                    } else {
                        //no
                        BigDecimal carryOverExcess = potentialTransferAmount
                                .subtract(adjustedMaxTransferAmount);
                        //move excess to forfeiture
                        bt.setForfeitedAmount(bt.getForfeitedAmount().add(carryOverExcess));
                        //the remainder (if any) can be added to the transfer amount.
                        bt.setTransferAmount(
                                bt.getTransferAmount().add(carryOverDiff.subtract(carryOverExcess)));

                        assert (bt.getTransferAmount().compareTo(adjustedMaxTransferAmount) == 0);
                        // assert that the new balance will be equal to the adjusted max carry over < adjusted max balance.
                    }
                }
                assert (adjustedMaxCarryOver.compareTo(
                        accruedBalance.subtract(bt.getTransferAmount().add(bt.getForfeitedAmount()))) == 0);
            }
            //otherwise, given balance will be at or under the max annual carry over.
        }

        bt.setEffectiveLocalDate(effectiveDate);
        bt.setAccrualCategoryRule(accrualCategoryRule);
        bt.setFromAccrualCategory(fromAccrualCategory.getAccrualCategory());
        bt.setPrincipalId(principalId);
        bt.setUserPrincipalId(HrContext.getPrincipalId());
        if (ObjectUtils.isNotNull(transferConversionFactor)) {
            bt.setAmountTransferred(bt.getTransferAmount().multiply(transferConversionFactor).setScale(2,
                    RoundingMode.HALF_UP));
        } else {
            bt.setAmountTransferred(bt.getTransferAmount());
        }
    }
    return bt;
}