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 * <p>
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 * <p>
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 * <p>
059 * <pre>
060 * public final class MyMoney implements MonetaryAmount{
061 *   ...
062 *   public static MyMoney from(MonetaryAmount amount)(...)
063 * }
064 * </pre>
065 * <p>
066 * </blockquote></li>
067 * </ul>
068 * <h4>Implementation specification</h4>
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 * <p>
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     * <p>
105     * This queries this amount using the specified query strategy object.
106     * <p>
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: <blockquote>
123     * <p>
124     * <pre>
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     * </blockquote>
130     * </pre>
131     * <p>
132     * This converts this monetary amount according to the rules of the specified operator. A
133     * typical operator will change the amount and leave the currency unchanged. A more complex
134     * operator might also change the currency.
135     * <p>
136     * Some example code indicating how and why this method is used:
137     * <p>
138     * <blockquote>
139     * <p>
140     * <pre>
141     * MonetaryAmount money = money.with(amountMultipliedBy(2));
142     * money = money.with(amountRoundedToNearestWholeUnit());
143     * </pre>
144     * <p>
145     * </blockquote>
146     * <p>
147     * Hereby also the method signature on the implementation type must return the concrete type, to
148     * enable a fluent API, e.g.
149     * <p>
150     * <blockquote>
151     * <p>
152     * <pre>
153     * public final class MyMoney implements MonetaryAmount{
154     *   ...
155     *   public MyMoney with(MonetaryOperator operator){
156     *     ...
157     *   }
158     *
159     *   ...
160     * }
161     * </pre>
162     * <p>
163     * </blockquote>
164     *
165     * @param operator the operator to use, not null
166     * @return an object of the same type with the specified conversion made, not null
167     */
168    public MonetaryAmount with(MonetaryOperator operator){
169        return operator.apply(this);
170    }
171
172
173    /**
174     * Checks if a {@code MonetaryAmount} is negative.
175     *
176     * @return {@code true} if {@link #signum()} < 0.
177     */
178    public boolean isNegative(){
179        return signum() < 0;
180    }
181
182    /**
183     * Checks if a {@code MonetaryAmount} is negative or zero.
184     *
185     * @return {@code true} if {@link #signum()} <= 0.
186     */
187    public boolean isNegativeOrZero(){
188        return signum() <= 0;
189    }
190
191    /**
192     * Checks if a {@code MonetaryAmount} is positive.
193     *
194     * @return {@code true} if {@link #signum()} > 0.
195     */
196    public boolean isPositive(){
197        return signum() > 0;
198    }
199
200    /**
201     * Checks if a {@code MonetaryAmount} is positive or zero.
202     *
203     * @return {@code true} if {@link #signum()} >= 0.
204     */
205    public boolean isPositiveOrZero(){
206        return signum() >= 0;
207    }
208
209    /**
210     * Checks if an {@code MonetaryAmount} is zero.
211     *
212     * @return {@code true} if {@link #signum()} == 0.
213     */
214    public boolean isZero(){
215        return signum() == 0;
216    }
217
218}