blob: ba58b25f73a3b4039a737bc441d55db3a29648f2 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.infrastructure.core.service;
import jakarta.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.math.MathContext;
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
import org.apache.fineract.organisation.monetary.domain.Money;
import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
public final class MathUtil {
private MathUtil() {
}
public static <E extends Number> E nullToDefault(E value, E def) {
return value == null ? def : value;
}
public static Long nullToZero(Long value) {
return nullToDefault(value, 0L);
}
public static Long nullToDefault(Long value, Long def) {
return value == null ? def : value;
}
public static Long zeroToNull(Long value) {
return isEmpty(value) ? null : value;
}
/** @return parameter value or ZERO if it is negative */
public static Long negativeToZero(Long value) {
return isGreaterThanZero(value) ? value : 0L;
}
public static boolean isEmpty(Long value) {
return value == null || value.equals(0L);
}
public static boolean isGreaterThanZero(Long value) {
return value != null && value > 0L;
}
public static boolean isLessThanZero(Long value) {
return value != null && value < 0L;
}
public static boolean isZero(Long value) {
return value != null && value.equals(0L);
}
public static boolean isEqualTo(Long first, Long second) {
return nullToZero(first).equals(nullToZero(second));
}
public static boolean isGreaterThan(Long first, Long second) {
return nullToZero(first) > nullToZero(second);
}
public static boolean isLessThan(Long first, Long second) {
return nullToZero(first) < nullToZero(second);
}
public static boolean isGreaterThanOrEqualTo(Long first, Long second) {
return nullToZero(first) >= nullToZero(second);
}
public static boolean isLessThanOrEqualZero(Long value) {
return nullToZero(value) <= 0L;
}
/** @return parameter value or negated value to positive */
public static Long abs(Long value) {
return value == null ? 0L : Math.abs(value);
}
/**
* @return calculates minimum of the two values considering null values
* @param notNull
* if true then null parameter is omitted, otherwise returns null
*/
public static Long min(Long first, Long second, boolean notNull) {
if (first == null) {
return notNull ? second : null;
}
if (second == null) {
return notNull ? first : null;
}
return Math.min(first, second);
}
/**
* @return calculates minimum of the values considering null values
* @param notNull
* if true then null parameter is omitted, otherwise returns null
*/
public static Long min(Long first, Long second, Long third, boolean notNull) {
return min(min(first, second, notNull), third, notNull);
}
/** @return sum the two values considering null values */
public static Long add(Long first, Long second) {
return first == null ? second : second == null ? first : Math.addExact(first, second);
}
/** @return sum the values considering null values */
public static Long add(Long first, Long second, Long third) {
return add(add(first, second), third);
}
/** @return sum the values considering null values */
public static Long add(Long first, Long second, Long third, Long fourth) {
return add(add(add(first, second), third), fourth);
}
/** @return sum the values considering null values */
public static Long add(Long first, Long second, Long third, Long fourth, Long fifth) {
return add(add(add(add(first, second), third), fourth), fifth);
}
/** @return first minus second considering null values, maybe negative */
public static Long subtract(Long first, Long second) {
return first == null ? null : second == null ? first : Math.subtractExact(first, second);
}
/**
* @return first minus the others considering null values, maybe negative
*/
public static Long subtractToZero(Long first, Long second, Long third) {
return subtractToZero(subtract(first, second), third);
}
/**
* @return first minus the others considering null values, maybe negative
*/
public static Long subtractToZero(Long first, Long second, Long third, Long fourth) {
return subtractToZero(subtract(subtract(first, second), third), fourth);
}
/** @return NONE negative first minus second considering null values */
public static Long subtractToZero(Long first, Long second) {
return negativeToZero(subtract(first, second));
}
/** @return BigDecimal null safe negate */
public static Long negate(Long amount) {
return isEmpty(amount) ? amount : Math.negateExact(amount);
}
// ----------------- BigDecimal -----------------
public static BigDecimal nullToZero(BigDecimal value) {
return nullToDefault(value, BigDecimal.ZERO);
}
public static BigDecimal nullToDefault(BigDecimal value, BigDecimal def) {
return value == null ? def : value;
}
public static BigDecimal zeroToNull(BigDecimal value) {
return isEmpty(value) ? null : value;
}
/** @return parameter value or ZERO if it is negative */
public static BigDecimal negativeToZero(BigDecimal value) {
return isGreaterThanZero(value) ? value : BigDecimal.ZERO;
}
public static boolean isEmpty(BigDecimal value) {
return value == null || BigDecimal.ZERO.compareTo(value) == 0;
}
public static boolean isGreaterThanZero(BigDecimal value) {
return value != null && value.compareTo(BigDecimal.ZERO) > 0;
}
public static boolean isLessThanZero(BigDecimal value) {
return value != null && value.compareTo(BigDecimal.ZERO) < 0;
}
public static boolean isZero(BigDecimal value) {
return value != null && value.compareTo(BigDecimal.ZERO) == 0;
}
public static boolean isEqualTo(BigDecimal first, BigDecimal second) {
return nullToZero(first).compareTo(nullToZero(second)) == 0;
}
public static boolean isGreaterThan(BigDecimal first, BigDecimal second) {
return nullToZero(first).compareTo(nullToZero(second)) > 0;
}
public static boolean isLessThan(BigDecimal first, BigDecimal second) {
return nullToZero(first).compareTo(nullToZero(second)) < 0;
}
public static boolean isGreaterThanOrEqualTo(BigDecimal first, BigDecimal second) {
return nullToZero(first).compareTo(nullToZero(second)) >= 0;
}
public static boolean isLessThanOrEqualZero(BigDecimal value) {
return nullToZero(value).compareTo(BigDecimal.ZERO) <= 0;
}
/** @return parameter value or negated value to positive */
public static BigDecimal abs(BigDecimal value) {
return value == null ? BigDecimal.ZERO : value.abs();
}
/**
* @return calculates minimum of the two values considering null values
* @param notNull
* if true then null parameter is omitted, otherwise returns null
*/
public static BigDecimal min(BigDecimal first, BigDecimal second, boolean notNull) {
return notNull ? first == null ? second : second == null ? first : min(first, second, false)
: isLessThan(first, second) ? first : second;
}
/**
* @return calculates minimum of the values considering null values
* @param notNull
* if true then null parameter is omitted, otherwise returns null
*/
public static BigDecimal min(BigDecimal first, BigDecimal second, BigDecimal third, boolean notNull) {
return min(min(first, second, notNull), third, notNull);
}
/** @return sum the two values considering null values */
public static BigDecimal add(BigDecimal first, BigDecimal second) {
return add(first, second, MoneyHelper.getMathContext());
}
/** @return sum the two values considering null values */
public static BigDecimal add(BigDecimal first, BigDecimal second, MathContext mc) {
return first == null ? second : second == null ? first : first.add(second, mc);
}
/** @return sum the values considering null values */
public static BigDecimal add(BigDecimal first, BigDecimal second, BigDecimal third) {
return add(first, second, third, MoneyHelper.getMathContext());
}
/** @return sum the values considering null values */
public static BigDecimal add(BigDecimal first, BigDecimal second, BigDecimal third, MathContext mc) {
return add(add(first, second, mc), third, mc);
}
/** @return sum the values considering null values */
public static BigDecimal add(BigDecimal first, BigDecimal second, BigDecimal third, BigDecimal fourth) {
return add(first, second, third, fourth, MoneyHelper.getMathContext());
}
/** @return sum the values considering null values */
public static BigDecimal add(BigDecimal first, BigDecimal second, BigDecimal third, BigDecimal fourth, MathContext mc) {
return add(add(add(first, second, mc), third, mc), fourth, mc);
}
/** @return sum the values considering null values */
public static BigDecimal add(BigDecimal first, BigDecimal second, BigDecimal third, BigDecimal fourth, BigDecimal fifth) {
return add(first, second, third, fourth, fifth, MoneyHelper.getMathContext());
}
/** @return sum the values considering null values */
public static BigDecimal add(BigDecimal first, BigDecimal second, BigDecimal third, BigDecimal fourth, BigDecimal fifth,
MathContext mc) {
return add(add(add(add(first, second, mc), third, mc), fourth, mc), fifth, mc);
}
/** @return first minus second considering null values, maybe negative */
public static BigDecimal subtract(BigDecimal first, BigDecimal second) {
return subtract(first, second, MoneyHelper.getMathContext());
}
/** @return first minus second considering null values, maybe negative */
public static BigDecimal subtract(BigDecimal first, BigDecimal second, MathContext mc) {
return first == null ? null : second == null ? first : first.subtract(second, mc);
}
/** @return NONE negative first minus second considering null values */
public static BigDecimal subtractToZero(BigDecimal first, BigDecimal second) {
return negativeToZero(subtract(first, second));
}
/**
* @return first minus the others considering null values, maybe negative
*/
public static BigDecimal subtractToZero(BigDecimal first, BigDecimal second, BigDecimal third) {
return subtractToZero(subtract(first, second), third);
}
/**
* @return first minus the others considering null values, maybe negative
*/
public static BigDecimal subtractToZero(BigDecimal first, BigDecimal second, BigDecimal third, BigDecimal fourth) {
return subtractToZero(subtract(subtract(first, second), third), fourth);
}
/**
* @return BigDecimal with scale set to the 'digitsAfterDecimal' of the parameter currency
*/
public static BigDecimal normalizeAmount(BigDecimal amount, @NotNull MonetaryCurrency currency) {
return amount == null ? null : amount.setScale(currency.getDigitsAfterDecimal(), MoneyHelper.getRoundingMode());
}
/** @return BigDecimal null safe negate */
public static BigDecimal negate(BigDecimal amount) {
return negate(amount, MoneyHelper.getMathContext());
}
/** @return BigDecimal null safe negate */
public static BigDecimal negate(BigDecimal amount, MathContext mc) {
return isEmpty(amount) ? amount : amount.negate(mc);
}
public static String formatToSql(BigDecimal amount) {
return amount == null ? null : amount.toPlainString();
}
// ----------------- Money -----------------
public static Money nullToZero(Money value, @NotNull MonetaryCurrency currency) {
return nullToDefault(value, Money.zero(currency));
}
public static Money nullToDefault(Money value, Money def) {
return value == null ? def : value;
}
public static Money zeroToNull(Money value) {
return isEmpty(value) ? null : value;
}
/** @return parameter value or ZERO if it is negative */
public static Money negativeToZero(Money value) {
return value == null || isGreaterThanZero(value) ? value : Money.zero(value.getCurrency());
}
public static boolean isEmpty(Money value) {
return value == null || value.isZero();
}
public static boolean isGreaterThanZero(Money value) {
return value != null && value.isGreaterThanZero();
}
public static boolean isLessThanZero(Money value) {
return value != null && value.isLessThanZero();
}
public static boolean isEqualTo(Money first, Money second) {
return first == null ? second == null : (second != null && first.isEqualTo(second));
}
public static boolean isGreaterThan(Money first, Money second) {
return second == null || (first != null && first.isGreaterThan(second));
}
public static boolean isLessThan(Money first, Money second) {
return first == null || (second != null && first.isLessThan(second));
}
public static Money plus(Money first, Money second) {
return first == null ? second : second == null ? first : first.plus(second);
}
public static Money plus(Money first, Money second, Money third) {
return plus(plus(first, second), third);
}
public static Money plus(Money first, Money second, Money third, Money fourth) {
return plus(plus(plus(first, second), third), fourth);
}
public static Money minus(Money first, Money second) {
return first == null ? null : second == null ? first : first.minus(second);
}
/**
* @return first minus the others considering null values, maybe negative
*/
public static Money minusToZero(Money first, Money second, Money third) {
return minusToZero(minus(first, second), third);
}
/**
* @return first minus the others considering null values, maybe negative
*/
public static Money minusToZero(Money first, Money second, Money third, Money fourth) {
return minusToZero(minus(minus(first, second), third), fourth);
}
/** @return NONE negative first minus second considering null values */
public static Money minusToZero(Money first, Money second) {
return negativeToZero(minus(first, second));
}
/**
* @return calculates minimum of the two values considering null values
* @param notNull
* if true then null parameter is omitted, otherwise returns null
*/
public static Money min(Money first, Money second, boolean notNull) {
return notNull ? first == null ? second : second == null ? first : min(first, second, false)
: isLessThan(first, second) ? first : second;
}
/**
* @return calculates minimum of the values considering null values
* @param notNull
* if true then null parameter is omitted, otherwise returns null
*/
public static Money min(Money first, Money second, Money third, boolean notNull) {
return min(min(first, second, notNull), third, notNull);
}
/**
* Calculate percentage of a value
*
* @param value
* @param percentage
* @param precision
* @return
*/
public static BigDecimal percentageOf(final BigDecimal value, final BigDecimal percentage, final int precision) {
BigDecimal percentageOf = BigDecimal.ZERO;
if (isGreaterThanZero(value)) {
final MathContext mc = new MathContext(precision, MoneyHelper.getRoundingMode());
final BigDecimal multiplicand = percentage.divide(BigDecimal.valueOf(100L), mc);
percentageOf = value.multiply(multiplicand, mc);
}
return percentageOf;
}
/**
* Calculate percentage of a value
*
* @param value
* @param percentage
* @param mc
* @return
*/
public static BigDecimal percentageOf(final BigDecimal value, final BigDecimal percentage, final MathContext mc) {
BigDecimal percentageOf = BigDecimal.ZERO;
if (isGreaterThanZero(value)) {
final BigDecimal multiplicand = percentage.divide(BigDecimal.valueOf(100L), mc);
percentageOf = value.multiply(multiplicand, mc);
}
return percentageOf;
}
}