All Downloads are FREE. Search and download functionalities are using the official Maven repository.

javax.money.MonetaryAmount Maven / Gradle / Ivy

Go to download

JSR 354 provides an API for representing, transporting, and performing comprehensive calculations with Money and Currency.

There is a newer version: 1.1
Show newest version
/*
 * CREDIT SUISSE IS WILLING TO LICENSE THIS SPECIFICATION TO YOU ONLY UPON THE CONDITION THAT YOU
 * ACCEPT ALL OF THE TERMS CONTAINED IN THIS AGREEMENT. PLEASE READ THE TERMS AND CONDITIONS OF THIS
 * AGREEMENT CAREFULLY. BY DOWNLOADING THIS SPECIFICATION, YOU ACCEPT THE TERMS AND CONDITIONS OF
 * THE AGREEMENT. IF YOU ARE NOT WILLING TO BE BOUND BY IT, SELECT THE "DECLINE" BUTTON AT THE
 * BOTTOM OF THIS PAGE. Specification: JSR-354 Money and Currency API ("Specification") Copyright
 * (c) 2012-2013, Credit Suisse All rights reserved.
 */
package javax.money;

/**
 * Interface defining a monetary amount. The effective format representation of an amount may vary
 * depending on the implementation used. JSR 354 explicitly supports different types of monetary
 * amounts to be implemented and used. Reason behind is that the requirements to an implementation
 * heavily vary for different usage scenarios. E.g. product calculations may require high precision
 * and scale, whereas low latency order and trading systems require high calculation performance for
 * algorithmic operations.
 * 

* Each instance of an amount provides additional meta-data in form of a {@link MonetaryContext}. * This context contains detailed information on the numeric capabilities, e.g. the supported * precision and maximal scale, as well as the common implementation flavor. * * Also a {@link MonetaryAmount} provides a {@link NumberValue}, which allows easily to extract the * numeric value, of the amount. And finally {@link #getFactory()} provides a * {@link MonetaryAmountFactory}, which allows to of instances of {@link MonetaryAmount} based * on the same numeric implementation. *

* This JSR additionally recommends to consider the following aspects: *

    *
  • Arithmetic operations should throw an {@link ArithmeticException}, if performing arithmetic * operations between amounts exceeds the capabilities of the numeric representation type used. Any * implicit truncating, that would lead to complete invalid and useless results, should be avoided. * This recommendation does not affect format rounding, as required by the format numeric * representation of a monetary amount. *
  • Monetary amounts should allow numbers as argument for arithmetic operations like division and * multiplication. Adding or subtracting of amounts must only be possible by passing instances of * {@link MonetaryAmount}.
  • *
  • Nevertheless numeric truncation is also explicitly supported when calling * {@link NumberValue#numberValue(Class)}, whereas the exact counterpart, * {@link NumberValue#numberValueExact(Class)}, works similar to * {@link java.math.BigDecimal#longValueExact()}. *
  • Since implementations are recommended to be immutable, an operation should never change any * format state of an instance. Given an instance, all operations are required to be fully * reproducible.
  • *
  • Finally the result of calling {@link #with(MonetaryOperator)} must be of the same type as * type on which {@code with} was called. The {@code with} method also defines additional * interoperability requirements that are important to enable this invariant.
  • *
  • To enable further interoperability a static method {@code from(MonetaryAmount)} is * recommended to be implemented on each implementation class, that allows conversion of a * {@code MonetaryAmount} to a concrete instance. E.g.a class {@code MyMoney extends MonetaryAmount} * would contain the following method: * *
    *

    *

     * public final class MyMoney implements MonetaryAmount{
     *   ...
     *   public static MyMoney from(MonetaryAmount amount)(...)
     * }
     * 
    *

    *

  • *
*

Implementation specification

* Implementations of this interface must be *
    *
  • thread-safe
  • *
* Implementations of this interface should be *
    *
  • final
  • *
  • serializable, hereby writing the numeric value, the {@link MonetaryContext} and a serialized * {@link CurrencyUnit}.
  • *
* Implementations of this interface must be *
    *
  • thread-safe
  • *
  • immutable
  • *
  • comparable
  • *
  • must implement {@code equals/hashCode}, hereby considering *
      *
    • Implementation type *
    • CurrencyUnit *
    • Numeric value. *
    * This also means that two different implementations types with the same currency and numeric value * are NOT equal.
  • *
*

* * @author Anatole Tresch * @author Werner Keil * @version 0.8.2 * @see #with(MonetaryOperator) */ public interface MonetaryAmount extends CurrencySupplier, NumberSupplier, Comparable{ /** * Returns the {@link MonetaryContext} of this {@code MonetaryAmount}. The * {@link MonetaryContext} provides additional information about the numeric representation and * the numeric capabilities. This information can be used by code to determine situations where * {@code MonetaryAmount} instances must be converted to avoid implicit truncation, which can * lead to invalid results. * * @return the {@link MonetaryContext} of this {@code MonetaryAmount}, never {@code null} . */ MonetaryContext getContext(); /** * Queries this monetary amount for a value. *

* This queries this amount using the specified query strategy object. *

* Implementations must ensure that no observable state is altered when this read-only method is * invoked. * * @param the type of the result * @param query the query to invoke, not null * @return the query result, null may be returned (defined by the query) */ default R query(MonetaryQuery query){ return query.queryFrom(this); } /** * Returns an operated object of the same type as this object with the operation made. * Hereby returning an instannce of the same type is very important to prevent * uncontrolled mixup of implementations. Switching between implementations is still easily * possible, e.g. by using according {@link MonetaryAmountFactory} instances:

*

*

     * // converting from Money to MyMoney
     * Money m = ...;
     * MonetartyAmountFactory f = Monetary.queryAmountFactory(MyMoney.class);
     * MyMoney myMoney = f.setAmount(m).of();
     * 
*
*

* This converts this monetary amount according to the rules of the specified operator. A * typical operator will change the amount and leave the currency unchanged. A more complex * operator might also change the currency. *

* Some example code indicating how and why this method is used: *

*

*

*

     * MonetaryAmount money = money.with(amountMultipliedBy(2));
     * money = money.with(amountRoundedToNearestWholeUnit());
     * 
*

*

*

* Hereby also the method signature on the implementation type must return the concrete type, to * enable a fluent API, e.g. *

*

*

*

     * public final class MyMoney implements MonetaryAmount{
     *   ...
     *   public MyMoney with(MonetaryOperator operator){
     *     ...
     *   }
     *
     *   ...
     * }
     * 
*

*

* * @param operator the operator to use, not null * @return an object of the same type with the specified conversion made, not null */ default MonetaryAmount with(MonetaryOperator operator){ return operator.apply(this); } /** * Creates a new {@code MonetaryAmountFactory}, returning the same implementation type Hereby * this given amount is used as a template, so reusing the {@link CurrencyUnit}, its numeric * value, the algorithmic implementation as well as the current {@link MonetaryContext}. *

* This method is used for creating a new amount result after having done calculations that are * not directly mappable to the default monetary arithmetics, e.g. currency conversion. * * @return the new {@code MonetaryAmountFactory} with the given {@link MonetaryAmount} as its * default values. */ MonetaryAmountFactory getFactory(); /** * Compares two instances of {@link MonetaryAmount}, hereby ignoring non significant trailing * zeroes and different numeric capabilities. * * @param amount the {@code MonetaryAmount} to be compared with this instance. * @return {@code true} if {@code amount > this}. * @throws MonetaryException if the amount's currency is not equals to the currency of this instance. */ boolean isGreaterThan(MonetaryAmount amount); /** * Compares two instances of {@link MonetaryAmount}, hereby ignoring non significant trailing * zeroes and different numeric capabilities. * * @param amount the {@link MonetaryAmount} to be compared with this instance. * @return {@code true} if {@code amount >= this}. * @throws MonetaryException if the amount's currency is not equals to the currency of this instance. */ boolean isGreaterThanOrEqualTo(MonetaryAmount amount); /** * Compares two instances of {@link MonetaryAmount}, hereby ignoring non significant trailing * zeroes and different numeric capabilities. * * @param amount the {@link MonetaryAmount} to be compared with this instance. * @return {@code true} if {@code amount < this}. * @throws MonetaryException if the amount's currency is not equals to the currency of this instance. */ boolean isLessThan(MonetaryAmount amount); /** * Compares two instances of {@link MonetaryAmount}, hereby ignoring non significant trailing * zeroes and different numeric capabilities. * * @param amt the {@link MonetaryAmount} to be compared with this instance. * @return {@code true} if {@code amount <= this}. * @throws MonetaryException if the amount's currency is not equals to the currency of this instance. */ boolean isLessThanOrEqualTo(MonetaryAmount amt); /** * Compares two instances of {@link MonetaryAmount}, hereby ignoring non significant trailing * zeroes and different numeric capabilities. * * @param amount the {@link MonetaryAmount} to be compared with this instance. * @return {@code true} if {@code amount == this}. * @throws MonetaryException if the amount's currency is not equals to the currency of this instance. */ boolean isEqualTo(MonetaryAmount amount); /** * Checks if a {@code MonetaryAmount} is negative. * * @return {@code true} if {@link #signum()} < 0. */ default boolean isNegative(){ return signum() < 0; } /** * Checks if a {@code MonetaryAmount} is negative or zero. * * @return {@code true} if {@link #signum()} <= 0. */ default boolean isNegativeOrZero(){ return signum() <= 0; } /** * Checks if a {@code MonetaryAmount} is positive. * * @return {@code true} if {@link #signum()} > 0. */ default boolean isPositive(){ return signum() > 0; } /** * Checks if a {@code MonetaryAmount} is positive or zero. * * @return {@code true} if {@link #signum()} >= 0. */ default boolean isPositiveOrZero(){ return signum() >= 0; } /** * Checks if an {@code MonetaryAmount} is zero. * * @return {@code true} if {@link #signum()} == 0. */ default boolean isZero(){ return signum() == 0; } /** * Returns the signum function of this {@code MonetaryAmount}. * * @return -1, 0, or 1 as the value of this {@code MonetaryAmount} is negative, zero, or * positive. */ int signum(); /** * Returns a {@code MonetaryAmount} whose value is this + amount, and whose scale is max(this.scale(), * amount.scale(). * * @param amount value to be added to this {@code MonetaryAmount}. * @return {@code this + amount} * @throws ArithmeticException if the result exceeds the numeric capabilities of this implementation class, i.e. * the {@link MonetaryContext} cannot be adapted as required. */ MonetaryAmount add(MonetaryAmount amount); /** * Returns a {@code MonetaryAmount} whose value is this - * amount, and whose scale is max(this.scale(), * subtrahend.scale(). * * @param amount value to be subtracted from this {@code MonetaryAmount}. * @return {@code this - amount} * @throws ArithmeticException if the result exceeds the numeric capabilities of this implementation class, i.e. * the {@link MonetaryContext} cannot be adapted as required. */ MonetaryAmount subtract(MonetaryAmount amount); /** * Returns a {@code MonetaryAmount} whose value is (this × * multiplicand), and whose scale is this.scale() + * multiplicand.scale(). * * @param multiplicand value to be multiplied by this {@code MonetaryAmount}. * @return {@code this * multiplicand} * @throws ArithmeticException if the result exceeds the numeric capabilities of this implementation class, i.e. * the {@link MonetaryContext} cannot be adapted as required. */ MonetaryAmount multiply(long multiplicand); /** * Returns a {@code MonetaryAmount} whose value is (this × * multiplicand), and whose scale is this.scale() + * multiplicand.scale(). * By default the input value's scale will be rounded to * accommodate the format capabilities, and no {@link java.lang.ArithmeticException} * is thrown if the input number's scale exceeds the capabilities. * * @param multiplicand value to be multiplied by this {@code MonetaryAmount}. If the multiplicand's scale exceeds * the * capabilities of the implementation, it may be rounded implicitly. * @return {@code this * multiplicand} * @throws ArithmeticException if the result exceeds the numeric capabilities of this implementation class, i.e. * the {@link MonetaryContext} cannot be adapted as required. */ MonetaryAmount multiply(double multiplicand); /** * Returns a {@code MonetaryAmount} whose value is (this × * multiplicand), and whose scale is this.scale() + * multiplicand.scale(). * * @param multiplicand value to be multiplied by this {@code MonetaryAmount}. If the multiplicand's scale exceeds * the * capabilities of the implementation, it may be rounded implicitly. * @return {@code this * multiplicand} * @throws ArithmeticException if the result exceeds the numeric capabilities of this implementation class, i.e. * the {@link MonetaryContext} cannot be adapted as required. */ MonetaryAmount multiply(Number multiplicand); /** * Returns a {@code MonetaryAmount} whose value is this / * divisor, and whose preferred scale is this.scale() - * divisor.scale(); if the exact quotient cannot be represented an {@code ArithmeticException} * is thrown. * * @param divisor value by which this {@code MonetaryAmount} is to be divided. * @return {@code this / divisor} * @throws ArithmeticException if the exact quotient does not have a terminating decimal expansion, or if the * result exceeds the numeric capabilities of this implementation class, i.e. the * {@link MonetaryContext} cannot be adapted as required. */ MonetaryAmount divide(long divisor); /** * Returns a {@code MonetaryAmount} whose value is this / * divisor, and whose preferred scale is this.scale() - * divisor.scale(); if the exact quotient cannot be represented an {@code ArithmeticException} * is thrown. * * @param divisor value by which this {@code MonetaryAmount} is to be divided. * @return {@code this / divisor} * @throws ArithmeticException if the exact quotient does not have a terminating decimal expansion, or if the * result exceeds the numeric capabilities of this implementation class, i.e. the * {@link MonetaryContext} cannot be adapted as required. */ MonetaryAmount divide(double divisor); /** * Returns a {@code MonetaryAmount} whose value is this / * divisor, and whose preferred scale is this.scale() - * divisor.scale(); if the exact quotient cannot be represented an {@code ArithmeticException} * is thrown. * * @param divisor value by which this {@code MonetaryAmount} is to be divided. * @return {@code this / divisor} * @throws ArithmeticException if the exact quotient does not have a terminating decimal expansion, or if the * result exceeds the numeric capabilities of this implementation class, i.e. the * {@link MonetaryContext} cannot be adapted as required. */ MonetaryAmount divide(Number divisor); /** * Returns a {@code MonetaryAmount} whose value is this % divisor. *

*

* The remainder is given by * this.subtract(this.divideToIntegralValue(divisor).multiply(divisor) . Note that this * is not the modulo operation (the result can be negative). * * @param divisor value by which this {@code MonetaryAmount} is to be divided. * @return {@code this % divisor}. * @throws ArithmeticException if {@code divisor==0}, or if the result exceeds the numeric capabilities of this * implementation class, i.e. the {@link MonetaryContext} cannot be adapted as * required. */ MonetaryAmount remainder(long divisor); /** * Returns a {@code MonetaryAmount} whose value is this % divisor. *

*

* The remainder is given by * this.subtract(this.divideToIntegralValue(divisor).multiply(divisor) . Note that this * is not the modulo operation (the result can be negative). * * @param divisor value by which this {@code MonetaryAmount} is to be divided. * @return {@code this % divisor}. * @throws ArithmeticException if {@code divisor==0}, or if the result exceeds the numeric capabilities of this * implementation class, i.e. the {@link MonetaryContext} cannot be adapted as * required. */ MonetaryAmount remainder(double divisor); /** * Returns a {@code MonetaryAmount} whose value is this % divisor. *

*

* The remainder is given by * this.subtract(this.divideToIntegralValue(divisor).multiply(divisor) . Note that this * is not the modulo operation (the result can be negative). * * @param divisor value by which this {@code MonetaryAmount} is to be divided. * @return {@code this % divisor}. * @throws ArithmeticException if {@code divisor==0}, or if the result exceeds the numeric capabilities of this * implementation class, i.e. the {@link MonetaryContext} cannot be adapted as * required. */ MonetaryAmount remainder(Number divisor); /** * Returns a two-element {@code MonetaryAmount} array containing the result of * {@code divideToIntegralValue} followed by the result of {@code remainder} on the two * operands. *

*

* Note that if both the integer quotient and remainder are needed, this method is faster than * using the {@code divideToIntegralValue} and {@code remainder} methods separately because the * division need only be carried out once. * * @param divisor value by which this {@code MonetaryAmount} is to be divided, and the remainder * computed. * @return a two element {@code MonetaryAmount} array: the quotient (the result of * {@code divideToIntegralValue}) is the initial element and the remainder is the final * element. * @throws ArithmeticException if {@code divisor==0}, or if the result exceeds the numeric capabilities of this * implementation class, i.e. the {@link MonetaryContext} cannot be adapted as * required. * @see #divideToIntegralValue(long) * @see #remainder(long) */ MonetaryAmount[] divideAndRemainder(long divisor); /** * Returns a two-element {@code MonetaryAmount} array containing the result of * {@code divideToIntegralValue} followed by the result of {@code remainder} on the two * operands. *

*

* Note that if both the integer quotient and remainder are needed, this method is faster than * using the {@code divideToIntegralValue} and {@code remainder} methods separately because the * division need only be carried out once. * * @param divisor value by which this {@code MonetaryAmount} is to be divided, and the remainder * computed. * @return a two element {@code MonetaryAmount} array: the quotient (the result of * {@code divideToIntegralValue}) is the initial element and the remainder is the final * element. * @throws ArithmeticException if {@code divisor==0}, or if the result exceeds the numeric capabilities of this * implementation class, i.e. the {@link MonetaryContext} cannot be adapted as * required. * @see #divideToIntegralValue(double) * @see #remainder(double) */ MonetaryAmount[] divideAndRemainder(double divisor); /** * Returns a two-element {@code MonetaryAmount} array containing the result of * {@code divideToIntegralValue} followed by the result of {@code remainder} on the two * operands. *

*

* Note that if both the integer quotient and remainder are needed, this method is faster than * using the {@code divideToIntegralValue} and {@code remainder} methods separately because the * division need only be carried out once. * * @param divisor value by which this {@code MonetaryAmount} is to be divided, and the remainder * computed. * @return a two element {@code MonetaryAmount} array: the quotient (the result of * {@code divideToIntegralValue}) is the initial element and the remainder is the final * element. * @throws ArithmeticException if {@code divisor==0}, or if the result exceeds the numeric capabilities of this * implementation class, i.e. the {@link MonetaryContext} cannot be adapted as * required. * @see #divideToIntegralValue(Number) * @see #remainder(Number) */ MonetaryAmount[] divideAndRemainder(Number divisor); /** * Returns a {@code MonetaryAmount} whose value is the integer part of the quotient * this / divisor rounded down. The preferred scale of the result is * this.scale() - * divisor.scale(). * * @param divisor value by which this {@code BigDecimal} is to be divided. * @return The integer part of {@code this / divisor}. * @throws ArithmeticException if {@code divisor==0} * @see java.math.BigDecimal#divideToIntegralValue(java.math.BigDecimal) */ MonetaryAmount divideToIntegralValue(long divisor); /** * Returns a {@code MonetaryAmount} whose value is the integer part of the quotient * this / divisor rounded down. The preferred scale of the result is * this.scale() - divisor.scale(). * * @param divisor value by which this {@code BigDecimal} is to be divided. * @return The integer part of {@code this / divisor}. * @throws ArithmeticException if {@code divisor==0} * @see java.math.BigDecimal#divideToIntegralValue(java.math.BigDecimal) */ MonetaryAmount divideToIntegralValue(double divisor); /** * Returns a {@code MonetaryAmount} whose value is the integer part of the quotient * this / divisor rounded down. The preferred scale of the result is * this.scale() - * divisor.scale(). * * @param divisor value by which this {@code BigDecimal} is to be divided. * @return The integer part of {@code this / divisor}. * @throws ArithmeticException if {@code divisor==0} * @see java.math.BigDecimal#divideToIntegralValue(java.math.BigDecimal) */ MonetaryAmount divideToIntegralValue(Number divisor); /** * Returns a {@code MonetaryAmount} whose numerical value is equal to ( {@code this} * * 10n). The scale of the result is this.scale() - n. * * @param power the power. * @return the calculated amount value. * @throws ArithmeticException if the scale would be outside the range of a 32-bit integer, or if the result * exceeds the numeric capabilities of this implementation class, i.e. the * {@link MonetaryContext} cannot be adapted as required. */ MonetaryAmount scaleByPowerOfTen(int power); /** * Returns a {@code MonetaryAmount} whose value is the absolute value of this * {@code MonetaryAmount}, and whose scale is {@code this.scale()}. * * @return abs(this */ MonetaryAmount abs(); /** * Returns a {@code MonetaryAmount} whose value is -this, and whose scale is * {@code this.scale()}. * * @return {@code -this}. */ MonetaryAmount negate(); /** * Returns a {@code MonetaryAmount} whose value is +this, with rounding according to * the context settings. * * @return {@code this}, rounded as necessary. A zero result will have a scale of 0. * @throws ArithmeticException if rounding fails. * @see java.math.BigDecimal#plus() */ MonetaryAmount plus(); /** * Returns a {@code MonetaryAmount} which is numerically equal to this one but with any trailing * zeros removed from the representation. For example, stripping the trailing zeros from the * {@code MonetaryAmount} value {@code CHF 600.0}, which has [{@code BigInteger}, {@code scale}] * components equals to [6000, 1], yields {@code 6E2} with [ {@code BigInteger}, {@code scale}] * components equals to [6, -2] * * @return a numerically equal {@code MonetaryAmount} with any trailing zeros removed. */ MonetaryAmount stripTrailingZeros(); }



© 2015 - 2024 Weber Informatics LLC | Privacy Policy