org.javamoney.moneta.spi.base.BaseMonetaryAmount Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of moneta-bp Show documentation
Show all versions of moneta-bp Show documentation
JSR 354 provides an API for representing, transporting, and performing comprehensive calculations with
Money and Currency.
This module implements JSR 354.
/*
* 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 org.javamoney.moneta.spi.base;
import javax.money.MonetaryAmount;
import javax.money.MonetaryOperator;
import javax.money.MonetaryQuery;
/**
* 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 javax.money.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 BaseMonetaryAmount} provides a {@link javax.money.NumberValue}, which allows easily to extract the
* numeric value, of the amount. And finally {@link #getFactory()} provides a
* {@link javax.money.MonetaryAmountFactory}, which allows to of instances of {@link BaseMonetaryAmount} 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 BaseMonetaryAmount}.
* - Nevertheless numeric truncation is also explicitly supported when calling
* {@link javax.money.NumberValue#numberValue(Class)}, whereas the exact counterpart,
* {@link javax.money.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(javax.money.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 javax.money.MonetaryContext} and a serialized
* {@link javax.money.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(javax.money.MonetaryOperator)
*/
public abstract class BaseMonetaryAmount implements MonetaryAmount{
/**
* 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)
*/
public 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 instance 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 javax.money.MonetaryAmountFactory} instances:
*
* {@code
* // converting from Money to MyMoney
* Money m = ...;
* MonetaryAmountFactory 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:
*
* {@code
* 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.
*
* {@code
* 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
*/
public MonetaryAmount with(MonetaryOperator operator){
return operator.apply(this);
}
/**
* Checks if a {@code MonetaryAmount} is negative.
*
* @return {@code true} if {@link #signum()} < 0.
*/
public boolean isNegative(){
return signum() < 0;
}
/**
* Checks if a {@code MonetaryAmount} is negative or zero.
*
* @return {@code true} if {@link #signum()} <= 0.
*/
public boolean isNegativeOrZero(){
return signum() <= 0;
}
/**
* Checks if a {@code MonetaryAmount} is positive.
*
* @return {@code true} if {@link #signum()} > 0.
*/
public boolean isPositive(){
return signum() > 0;
}
/**
* Checks if a {@code MonetaryAmount} is positive or zero.
*
* @return {@code true} if {@link #signum()} >= 0.
*/
public boolean isPositiveOrZero(){
return signum() >= 0;
}
/**
* Checks if an {@code MonetaryAmount} is zero.
*
* @return {@code true} if {@link #signum()} == 0.
*/
public boolean isZero(){
return signum() == 0;
}
}