001/*
002 * CREDIT SUISSE IS WILLING TO LICENSE THIS SPECIFICATION TO YOU ONLY UPON THE CONDITION THAT YOU
003 * ACCEPT ALL OF THE TERMS CONTAINED IN THIS AGREEMENT. PLEASE READ THE TERMS AND CONDITIONS OF THIS
004 * AGREEMENT CAREFULLY. BY DOWNLOADING THIS SPECIFICATION, YOU ACCEPT THE TERMS AND CONDITIONS OF
005 * THE AGREEMENT. IF YOU ARE NOT WILLING TO BE BOUND BY IT, SELECT THE "DECLINE" BUTTON AT THE
006 * BOTTOM OF THIS PAGE. Specification: JSR-354 Money and Currency API ("Specification") Copyright
007 * (c) 2012-2013, Credit Suisse All rights reserved.
008 */
009package org.javamoney.moneta.spi.base;
010
011import javax.money.MonetaryAmount;
012import javax.money.MonetaryOperator;
013import javax.money.MonetaryQuery;
014
015/**
016 * Interface defining a monetary amount. The effective format representation of an amount may vary
017 * depending on the implementation used. JSR 354 explicitly supports different types of monetary
018 * amounts to be implemented and used. Reason behind is that the requirements to an implementation
019 * heavily vary for different usage scenarios. E.g. product calculations may require high precision
020 * and scale, whereas low latency order and trading systems require high calculation performance for
021 * algorithmic operations.
022 *
023 * Each instance of an amount provides additional meta-data in form of a {@link javax.money.MonetaryContext}.
024 * This context contains detailed information on the numeric capabilities, e.g. the supported
025 * precision and maximal scale, as well as the common implementation flavor.
026 *
027 * Also a {@link BaseMonetaryAmount} provides a {@link javax.money.NumberValue}, which allows easily to extract the
028 * numeric value, of the amount. And finally {@link #getFactory()} provides a
029 * {@link javax.money.MonetaryAmountFactory}, which allows to of instances of {@link BaseMonetaryAmount} based
030 * on the same numeric implementation.
031 *
032 * This JSR additionally recommends to consider the following aspects:
033 * <ul>
034 * <li>Arithmetic operations should throw an {@link ArithmeticException}, if performing arithmetic
035 * operations between amounts exceeds the capabilities of the numeric representation type used. Any
036 * implicit truncating, that would lead to complete invalid and useless results, should be avoided.
037 * This recommendation does not affect format rounding, as required by the format numeric
038 * representation of a monetary amount.
039 * <li>Monetary amounts should allow numbers as argument for arithmetic operations like division and
040 * multiplication. Adding or subtracting of amounts must only be possible by passing instances of
041 * {@link BaseMonetaryAmount}.</li>
042 * <li>Nevertheless numeric truncation is also explicitly supported when calling
043 * {@link javax.money.NumberValue#numberValue(Class)}, whereas the <i>exact</i> counterpart,
044 * {@link javax.money.NumberValue#numberValueExact(Class)}, works similar to
045 * {@link java.math.BigDecimal#longValueExact()}.
046 * <li>Since implementations are recommended to be immutable, an operation should never change any
047 * format state of an instance. Given an instance, all operations are required to be fully
048 * reproducible.</li>
049 * <li>Finally the result of calling {@link #with(javax.money.MonetaryOperator)} must be of the same type as
050 * type on which {@code with} was called. The {@code with} method also defines additional
051 * interoperability requirements that are important to enable this invariant.</li>
052 * <li>To enable further interoperability a static method {@code from(MonetaryAmount)} is
053 * recommended to be implemented on each implementation class, that allows conversion of a
054 * {@code MonetaryAmount} to a concrete instance. E.g.a class {@code MyMoney extends MonetaryAmount}
055 * would contain the following method:
056 *
057 * <blockquote>
058 *
059 * <pre>
060 * public final class MyMoney implements MonetaryAmount{
061 *   ...
062 *   public static MyMoney from(MonetaryAmount amount)(...)
063 * }
064 * </pre>
065 *
066 * </blockquote></li>
067 * </ul>
068 * <b>Implementation specification</b>
069 * Implementations of this interface must be
070 * <ul>
071 * <li>thread-safe</li>
072 * </ul>
073 * Implementations of this interface should be
074 * <ul>
075 * <li>final</li>
076 * <li>serializable, hereby writing the numeric value, the {@link javax.money.MonetaryContext} and a serialized
077 * {@link javax.money.CurrencyUnit}.</li>
078 * </ul>
079 * Implementations of this interface must be
080 * <ul>
081 * <li>thread-safe</li>
082 * <li>immutable</li>
083 * <li>comparable</li>
084 * <li>must implement {@code equals/hashCode}, hereby considering
085 * <ul>
086 * <li>Implementation type
087 * <li>CurrencyUnit
088 * <li>Numeric value.
089 * </ul>
090 * This also means that two different implementations types with the same currency and numeric value
091 * are NOT equal.</li>
092 * </ul>
093 *
094 *
095 * @author Anatole Tresch
096 * @author Werner Keil
097 * @version 0.8.2
098 * @see #with(javax.money.MonetaryOperator)
099 */
100public abstract class BaseMonetaryAmount implements MonetaryAmount{
101
102    /**
103     * Queries this monetary amount for a value.
104     *
105     * This queries this amount using the specified query strategy object.
106     *
107     * Implementations must ensure that no observable state is altered when this read-only method is
108     * invoked.
109     *
110     * @param <R>   the type of the result
111     * @param query the query to invoke, not null
112     * @return the query result, null may be returned (defined by the query)
113     */
114    public <R> R query(MonetaryQuery<R> query){
115        return query.queryFrom(this);
116    }
117
118    /**
119     * Returns an operated object <b>of the same type</b> as this object with the operation made.
120     * Hereby returning an instance <b>of the same type</b> is very important to prevent
121     * uncontrolled mixup of implementations. Switching between implementations is still easily
122     * possible, e.g. by using according {@link javax.money.MonetaryAmountFactory} instances:
123     *
124     * {@code
125     * // converting from Money to MyMoney
126     * Money m = ...;
127     * MonetaryAmountFactory<MyMoney> f = Monetary.queryAmountFactory(MyMoney.class);
128     * MyMoney myMoney = f.setAmount(m).of();
129     * }
130     *
131     * This converts this monetary amount according to the rules of the specified operator. A
132     * typical operator will change the amount and leave the currency unchanged. A more complex
133     * operator might also change the currency.
134     *
135     * Some example code indicating how and why this method is used:
136     *
137     * {@code
138     * MonetaryAmount money = money.with(amountMultipliedBy(2));
139     * money = money.with(amountRoundedToNearestWholeUnit());
140     * }
141     *
142     * Hereby also the method signature on the implementation type must return the concrete type, to
143     * enable a fluent API, e.g.
144     *
145     * {@code
146     * public final class MyMoney implements MonetaryAmount{
147     *   ...
148     *   public MyMoney with(MonetaryOperator operator){
149     *     ...
150     *   }
151     *
152     *   ...
153     * }
154     * }
155     *
156     * @param operator the operator to use, not null
157     * @return an object of the same type with the specified conversion made, not null
158     */
159    public MonetaryAmount with(MonetaryOperator operator){
160        return operator.apply(this);
161    }
162
163
164    /**
165     * Checks if a {@code MonetaryAmount} is negative.
166     *
167     * @return {@code true} if {@link #signum()} &lt; 0.
168     */
169    public boolean isNegative(){
170        return signum() < 0;
171    }
172
173    /**
174     * Checks if a {@code MonetaryAmount} is negative or zero.
175     *
176     * @return {@code true} if {@link #signum()} &lt;= 0.
177     */
178    public boolean isNegativeOrZero(){
179        return signum() <= 0;
180    }
181
182    /**
183     * Checks if a {@code MonetaryAmount} is positive.
184     *
185     * @return {@code true} if {@link #signum()} &gt; 0.
186     */
187    public boolean isPositive(){
188        return signum() > 0;
189    }
190
191    /**
192     * Checks if a {@code MonetaryAmount} is positive or zero.
193     *
194     * @return {@code true} if {@link #signum()} &gt;= 0.
195     */
196    public boolean isPositiveOrZero(){
197        return signum() >= 0;
198    }
199
200    /**
201     * Checks if an {@code MonetaryAmount} is zero.
202     *
203     * @return {@code true} if {@link #signum()} == 0.
204     */
205    public boolean isZero(){
206        return signum() == 0;
207    }
208
209}