2323 * high precision and scale, whereas low latency order and trading systems
2424 * require high calculation performance for algorithmic operations.
2525 * <p>
26- * This JSR additionally defines a couple of interoperability rules that each
27- * implementation must follow:
26+ * This JSR additionally recommends to consider the following aspects:
2827 * <ul>
29- * <li>The numeric values on the MonetaryAmount interface are for
30- * interoperability only. They should not used for calculations. Instead of each
31- * implementation of this interface must provide a static method
32- * {@code T from(MonetaryAmount)} to create an instance of a concrete
33- * implementation type {@code T} based on a given amount instance.</li>
28+ * <li>Arithmetic operations should throw an {@link ArithmeticException}, if
29+ * performing arithmetic operations between amounts exceeds the capabilities of
30+ * the numeric representation type used. Any implicit truncating, that would
31+ * lead to complete invalid and useless results, should be avoided. This
32+ * recommendation does not affect internal rounding, as required by the internal
33+ * numeric representation of a monetary amount.
34+ * <li>Monetary amounts should allow numbers as argument for arithmetic
35+ * operations like division and multiplication additionally to a MonetaryAmount.
36+ * Adding or subtracting of amounts must only be possible by passing instances
37+ * of MonetaryAmount. Arguments of type {@link Number} should be avoided, since
38+ * it does not allow to extract its numeric value in a feasible way.
3439 * <li>If the numeric representation of a {@code MonetaryAmount} exceeds the
35- * numeric capabilities of the concrete type {@code T from(MonetaryAmount)} must
36- * throw an {@code ArithemticOperationException}.</li>
40+ * numeric capabilities of the concrete type {@code T from(MonetaryAmount)}, an
41+ * implementation should throw an {@code ArithemticOperationException}.</li>
3742 * <li>On the other hand, when the numeric value can not be mapped into the
3843 * numeric exchange format defined by this interface, by default also an
39- * {@code ArithmeticException} must be thrown. Never should truncation be
44+ * {@code ArithmeticException} should be thrown. Never should truncation be
4045 * performed implicitly.</li>
41- * <li>Nevertheless truncation is possible, but must be enabled explicitly by
42- * passing an additional {@code boolean} parameter as {@code true} to allow it.</li>
43- * <li>Rounding is never done automatically, exception internal rounding implied
44- * by the numeric implementation type.</li>
45- * <li>Since implementations are required to be immutable, an operation must
46- * never change any internal state of an instance. Given an instance, all
46+ * <li>Nevertheless truncation may be supported by passing additional parameters
47+ * or using <i>exact</i> methods, similar to {@link BigDecimal#longValueExact()}.
48+ * <li>Rounding should never be done automatically, exception internal rounding
49+ * implied by the numeric implementation type.</li>
50+ * <li>Since implementations are recommended to be immutable, an operation
51+ * should never change any internal state of an instance. Given an instance, all
4752 * operations are required to be fully reproducible.</li>
48- * <li>Finally the result of calling {@link #with(MonetaryAdjuster)} must be of
49- * the same type as type on which {@code with} was called. The {@code with}
53+ * <li>Finally the result of calling {@link #with(MonetaryAdjuster)} should be
54+ * of the same type as type on which {@code with} was called. The {@code with}
5055 * method also defines additional interoperability requirements.</li>
56+ * <li>To enable interoperability a static method {@code from(MonetaryAmount)}
57+ * is recommended to be implemented, that allows conversion of a
58+ * {@code MonetaryAmount} to a concrete type {@code T}:<br/>
59+ *
60+ * <pre>
61+ * public static T from(MonetaryAmount amount);}
62+ * </pre>
63+ *
64+ * This is particularly useful when implementing monetary adjusters or queries,
65+ * since arithmetic operations are not available on the MonetaryAmount
66+ * interface, which is defined for interoperability only.</li>
67+ * <li>Finally implementations should not implement a method {@code getAmount()}
68+ * . This methid is reserved for future integration into the JDK.</li>
5169 * </ul>
52- * It is required that implementations of this interface are
70+ * <h4>Implementation specification</h4>
71+ * Implementations of this interface should be
5372 * <ul>
5473 * <li>immutable</li>
5574 * <li>thread-safe</li>
5675 * <li>final</li>
57- * <li>serializable, hereby writing the numeric representation, e.g.
58- * {@link BigDecimal} and a serialized {@link CurrencyUnit}.</li>
76+ * <li>serializable, hereby writing the numeric value and a serialized
77+ * {@link CurrencyUnit}.</li>
78+ * </ul>
79+ * Implementations of this interface must be
80+ * <ul>
81+ * <li>comparable</li>
82+ * <li>must implement {@code equals/hashCode}, hereby considering
83+ * <ul>
84+ * <li>Implementation type
85+ * <li>CurrencyUnit
86+ * <li>Numeric value.
87+ * </ul>
88+ * This also means that two different implementations types with the same
89+ * currency and numeric value are NOT equal.</li>
90+ * <li>Additionally for the numeric representation of an amount,
91+ * <pre>
92+ * given w = getAmountWhole()
93+ * n = getFractionNominator()
94+ * d = getFractionDenominator()
95+ *
96+ * the following must be always true:
97+ *
98+ * !(w<0 && n>0) and
99+ * !(w>0 && n<0) and
100+ * d>0 and
101+ * |n| < d // || = absolute value
102+ * </pre>
59103 * </ul>
60104 * <p>
61105 * Since {@link Number} is not an interface, this type is not extending
68112public interface MonetaryAmount {
69113
70114 /**
71- * Gets the amount's currency.
115+ * Returns the amount’s currency, modelled as {@link CurrencyUnit}.
116+ * Implementations may co-variantly change the return type to a more
117+ * specific implementation of {@link CurrencyUnit} if desired.
72118 *
73119 * @return the currency, never {@code null}
74120 */
@@ -83,8 +129,14 @@ public interface MonetaryAmount {
83129 * <p>
84130 * For example, the amount of '12 dollars and 25 cents' would return 12 from
85131 * this method, as there are 12 whole US dollars in the amount.
132+ * <p>
133+ * Hereby it is always required that
134+ * <ul>
135+ * <li>{@code !(amountWhole<0 && fractionNumerator > 0) }
136+ * <li>{@code !(amountWhole>0 && fractionNumerator < 0) }
137+ * </ul>
86138 *
87- * @return the currency, not null
139+ * @return the amount's whole number
88140 */
89141 public long getAmountWhole ();
90142
@@ -97,8 +149,13 @@ public interface MonetaryAmount {
97149 * <p>
98150 * For example, the amount of '12 dollars and 25 cents' would typically
99151 * return 25 from this method and 100 from the denominator method.
152+ * <p>
153+ * Hereby it is always required that
154+ * <ul>
155+ * <li>{@code fractionNumerator < fractionDenominator}
156+ * </ul>
100157 *
101- * @return the currency, not null
158+ * @return the fraction numerator
102159 */
103160 public long getAmountFractionNumerator ();
104161
@@ -111,8 +168,16 @@ public interface MonetaryAmount {
111168 * <p>
112169 * For example, the amount of '12 dollars and 25 cents' would typically
113170 * return 100 from this method and 25 from the numerator method.
171+ * <p>
172+ * Hereby it is always required that
173+ * <ul>
174+ * <li>{@code fractionDenominator > 0}.
175+ * <li>{@code fractionDenominator > abs(fractionNominator)}.
176+ * <li>it is recommended that the denominator is a power of 10 (1, 10, 100,
177+ * 1000,...).
178+ * </ul>
114179 *
115- * @return the currency, not null
180+ * @return the fraction denominator
116181 */
117182 public long getAmountFractionDenominator ();
118183
0 commit comments