← joda-money  /  src/main/java/org/joda/money/Money.java

1
/*
2
 *  Copyright 2009-present, Stephen Colebourne
3
 *
4
 *  Licensed under the Apache License, Version 2.0 (the "License");
5
 *  you may not use this file except in compliance with the License.
6
 *  You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 *  Unless required by applicable law or agreed to in writing, software
11
 *  distributed under the License is distributed on an "AS IS" BASIS,
12
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 *  See the License for the specific language governing permissions and
14
 *  limitations under the License.
15
 */
16
package org.joda.money;
17
18
import java.io.InvalidObjectException;
19
import java.io.ObjectInputStream;
20
import java.io.Serializable;
21
import java.math.BigDecimal;
22
import java.math.RoundingMode;
23
import java.util.Arrays;
24
25
import org.joda.convert.FromString;
26
import org.joda.convert.ToString;
27
28
/**
29
 * An amount of money with the standard decimal places defined by the currency.
30
 * <p>
31
 * This class represents a quantity of money, stored as a {@code BigDecimal} amount
32
 * in a single {@link CurrencyUnit currency}.
33
 * <p>
34
 * Every currency has a certain standard number of decimal places.
35
 * This is typically 2 (Euro, British Pound, US Dollar) but might be
36
 * 0 (Japanese Yen), 1 (Vietnamese Dong) or 3 (Bahrain Dinar).
37
 * The {@code Money} class is fixed to this number of decimal places.
38
 * <p>
39
 * For example, US dollars has a standard number of decimal places of 2.
40
 * The major units are dollars. The minor units are cents, 100 to the dollar.
41
 * This class does not allow calculations on fractions of a cent.
42
 * <p>
43
 * This class is immutable and thread-safe.
44
 */
45
public final class Money implements BigMoneyProvider, Comparable<BigMoneyProvider>, Serializable {
46
47
    /**
48
     * The serialisation version.
49
     */
50
    private static final long serialVersionUID = 1L;
51
52
    /**
53
     * The money, not null.
54
     */
55
    private final BigMoney money;
56
57
    //-----------------------------------------------------------------------
58
    /**
59
     * Obtains an instance of {@code Money} from a {@code BigDecimal}.
60
     * <p>
61
     * This allows you to create an instance with a specific currency and amount.
62
     * No rounding is performed on the amount, so it must have a scale compatible
63
     * with the currency.
64
     *
65
     * @param currency  the currency, not null
66
     * @param amount  the amount of money, not null
67
     * @return the new instance, never null
68
     * @throws ArithmeticException if the scale exceeds the currency scale
69
     */
70
    public static Money of(CurrencyUnit currency, BigDecimal amount) {
71
        MoneyUtils.checkNotNull(currency, "Currency must not be null");
72
        MoneyUtils.checkNotNull(amount, "Amount must not be null");
73
        if (amount.scale() > currency.getDecimalPlaces()) {
74
            throw new ArithmeticException("Scale of amount " + amount + " is greater than the scale of the currency " + currency);
75
        }
76
        return Money.of(currency, amount, RoundingMode.UNNECESSARY);
77
    }
78
79
    /**
80
     * Obtains an instance of {@code Money} from a {@code BigDecimal}, rounding as necessary.
81
     * <p>
82
     * This allows you to create an instance with a specific currency and amount.
83
     * If the amount has a scale in excess of the scale of the currency then the excess
84
     * fractional digits are rounded using the rounding mode.
85
     *
86
     * @param currency  the currency, not null
87
     * @param amount  the amount of money, not null
88
     * @param roundingMode  the rounding mode to use, not null
89
     * @return the new instance, never null
90
     * @throws ArithmeticException if the rounding fails
91
     */
92
    public static Money of(CurrencyUnit currency, BigDecimal amount, RoundingMode roundingMode) {
93
        MoneyUtils.checkNotNull(currency, "CurrencyUnit must not be null");
94
        MoneyUtils.checkNotNull(amount, "Amount must not be null");
95
        MoneyUtils.checkNotNull(roundingMode, "RoundingMode must not be null");
96
        var scaledAmount = amount.setScale(currency.getDecimalPlaces(), roundingMode);
97
        return new Money(BigMoney.of(currency, scaledAmount));
98
    }
99
100
    //-----------------------------------------------------------------------
101
    /**
102
     * Obtains an instance of {@code Money} from a {@code double} using a
103
     * well-defined conversion.
104
     * <p>
105
     * This allows you to create an instance with a specific currency and amount.
106
     * No rounding is performed on the amount, so it must have a scale compatible
107
     * with the currency.
108
     * <p>
109
     * The amount is converted via {@link BigDecimal#valueOf(double)} which yields
110
     * the most expected answer for most programming scenarios.
111
     * Any {@code double} literal in code will be converted to
112
     * exactly the same BigDecimal with the same scale.
113
     * For example, the literal '1.45d' will be converted to '1.45'.
114
     *
115
     * @param currency  the currency, not null
116
     * @param amount  the amount of money, not null
117
     * @return the new instance, never null
118
     * @throws ArithmeticException if the scale exceeds the currency scale
119
     */
120
    public static Money of(CurrencyUnit currency, double amount) {
121
        return Money.of(currency, BigDecimal.valueOf(amount));
122
    }
123
124
    /**
125
     * Obtains an instance of {@code Money} from a {@code double} using a
126
     * well-defined conversion, rounding as necessary.
127
     * <p>
128
     * This allows you to create an instance with a specific currency and amount.
129
     * If the amount has a scale in excess of the scale of the currency then the excess
130
     * fractional digits are rounded using the rounding mode.
131
     * <p>
132
     * The amount is converted via {@link BigDecimal#valueOf(double)} which yields
133
     * the most expected answer for most programming scenarios.
134
     * Any {@code double} literal in code will be converted to
135
     * exactly the same BigDecimal with the same scale.
136
     * For example, the literal '1.45d' will be converted to '1.45'.
137
     *
138
     * @param currency  the currency, not null
139
     * @param amount  the amount of money, not null
140
     * @param roundingMode  the rounding mode to use, not null
141
     * @return the new instance, never null
142
     * @throws ArithmeticException if the rounding fails
143
     */
144
    public static Money of(CurrencyUnit currency, double amount, RoundingMode roundingMode) {
145
        return Money.of(currency, BigDecimal.valueOf(amount), roundingMode);
146
    }
147
148
    //-----------------------------------------------------------------------
149
    /**
150
     * Obtains an instance of {@code Money} from an amount in major units.
151
     * <p>
152
     * This allows you to create an instance with a specific currency and amount.
153
     * The amount is a whole number only. Thus you can initialise the value
154
     * 'USD 20', but not the value 'USD 20.32'.
155
     * For example, {@code ofMajor(USD, 25)} creates the instance {@code USD 25.00}.
156
     *
157
     * @param currency  the currency, not null
158
     * @param amountMajor  the amount of money in the major division of the currency
159
     * @return the new instance, never null
160
     */
161
    public static Money ofMajor(CurrencyUnit currency, long amountMajor) {
162
        return Money.of(currency, BigDecimal.valueOf(amountMajor), RoundingMode.UNNECESSARY);
163
    }
164
165
    /**
166
     * Obtains an instance of {@code Money} from an amount in minor units.
167
     * <p>
168
     * This allows you to create an instance with a specific currency and amount
169
     * expressed in terms of the minor unit.
170
     * For example, if constructing US Dollars, the input to this method represents cents.
171
     * Note that when a currency has zero decimal places, the major and minor units are the same.
172
     * For example, {@code ofMinor(USD, 2595)} creates the instance {@code USD 25.95}.
173
     *
174
     * @param currency  the currency, not null
175
     * @param amountMinor  the amount of money in the minor division of the currency
176
     * @return the new instance, never null
177
     */
178
    public static Money ofMinor(CurrencyUnit currency, long amountMinor) {
179
        return new Money(BigMoney.ofMinor(currency, amountMinor));
180
    }
181
182
    //-----------------------------------------------------------------------
183
    /**
184
     * Obtains an instance of {@code Money} representing zero.
185
     * <p>
186
     * For example, {@code zero(USD)} creates the instance {@code USD 0.00}.
187
     *
188
     * @param currency  the currency, not null
189
     * @return the instance representing zero, never null
190
     */
191
    public static Money zero(CurrencyUnit currency) {
192
        MoneyUtils.checkNotNull(currency, "Currency must not be null");
193
        var bd = BigDecimal.valueOf(0, currency.getDecimalPlaces());
194
        return new Money(BigMoney.of(currency, bd));
195
    }
196
197
    //-----------------------------------------------------------------------
198
    /**
199
     * Obtains an instance of {@code Money} from a provider.
200
     * <p>
201
     * This allows you to create an instance from any class that implements the
202
     * provider, such as {@code BigMoney}.
203
     * No rounding is performed on the amount, so it must have a scale compatible
204
     * with the currency.
205
     *
206
     * @param moneyProvider  the money to convert, not null
207
     * @return the new instance, never null
208
     * @throws ArithmeticException if the scale exceeds the currency scale
209
     */
210
    public static Money of(BigMoneyProvider moneyProvider) {
211
        return Money.of(moneyProvider, RoundingMode.UNNECESSARY);
212
    }
213
214
    /**
215
     * Obtains an instance of {@code Money} from a provider, rounding as necessary.
216
     * <p>
217
     * This allows you to create an instance from any class that implements the
218
     * provider, such as {@code BigMoney}.
219
     * The rounding mode is used to adjust the scale to the scale of the currency.
220
     *
221
     * @param moneyProvider  the money to convert, not null
222
     * @param roundingMode  the rounding mode to use, not null
223
     * @return the new instance, never null
224
     * @throws ArithmeticException if the rounding fails
225
     */
226
    public static Money of(BigMoneyProvider moneyProvider, RoundingMode roundingMode) {
227
        MoneyUtils.checkNotNull(moneyProvider, "BigMoneyProvider must not be null");
228
        MoneyUtils.checkNotNull(roundingMode, "RoundingMode must not be null");
229
        return new Money(BigMoney.of(moneyProvider).withCurrencyScale(roundingMode));
230
    }
231
232
    //-----------------------------------------------------------------------
233
    /**
234
     * Obtains an instance of {@code Money} as the total value of an array.
235
     * <p>
236
     * The array must contain at least one monetary value.
237
     * Subsequent amounts are added as though using {@link #plus(Money)}.
238
     * All amounts must be in the same currency.
239
     *
240
     * @param monies  the monetary values to total, not empty, no null elements, not null
241
     * @return the total, never null
242
     * @throws IllegalArgumentException if the array is empty
243
     * @throws CurrencyMismatchException if the currencies differ
244
     */
245
    public static Money total(Money... monies) {
246
        MoneyUtils.checkNotNull(monies, "Money array must not be null");
247
        if (monies.length == 0) {
248
            throw new IllegalArgumentException("Money array must not be empty");
249
        }
250
        var total = monies[0];
251
        MoneyUtils.checkNotNull(total, "Money arary must not contain null entries");
252
        for (var i = 1; i < monies.length; i++) {
253
            total = total.plus(monies[i]);
254
        }
255
        return total;
256
    }
257
258
    /**
259
     * Obtains an instance of {@code Money} as the total value of a collection.
260
     * <p>
261
     * The iterable must provide at least one monetary value.
262
     * Subsequent amounts are added as though using {@link #plus(Money)}.
263
     * All amounts must be in the same currency.
264
     *
265
     * @param monies  the monetary values to total, not empty, no null elements, not null
266
     * @return the total, never null
267
     * @throws IllegalArgumentException if the iterable is empty
268
     * @throws CurrencyMismatchException if the currencies differ
269
     */
270
    public static Money total(Iterable<Money> monies) {
271
        MoneyUtils.checkNotNull(monies, "Money iterator must not be null");
272
        var it = monies.iterator();
273
        if (!it.hasNext()) {
274
            throw new IllegalArgumentException("Money iterator must not be empty");
275
        }
276
        var total = it.next();
277
        MoneyUtils.checkNotNull(total, "Money iterator must not contain null entries");
278
        while (it.hasNext()) {
279
            total = total.plus(it.next());
280
        }
281
        return total;
282
    }
283
284
    /**
285
     * Obtains an instance of {@code Money} as the total value of
286
     * a possibly empty array.
287
     * <p>
288
     * The amounts are added as though using {@link #plus(Money)} starting
289
     * from zero in the specified currency.
290
     * All amounts must be in the same currency.
291
     *
292
     * @param currency  the currency to total in, not null
293
     * @param monies  the monetary values to total, no null elements, not null
294
     * @return the total, never null
295
     * @throws CurrencyMismatchException if the currencies differ
296
     */
297
    public static Money total(CurrencyUnit currency, Money... monies) {
298
        return Money.zero(currency).plus(Arrays.asList(monies));
299
    }
300
301
    /**
302
     * Obtains an instance of {@code Money} as the total value of
303
     * a possibly empty collection.
304
     * <p>
305
     * The amounts are added as though using {@link #plus(Money)} starting
306
     * from zero in the specified currency.
307
     * All amounts must be in the same currency.
308
     *
309
     * @param currency  the currency to total in, not null
310
     * @param monies  the monetary values to total, no null elements, not null
311
     * @return the total, never null
312
     * @throws CurrencyMismatchException if the currencies differ
313
     */
314
    public static Money total(CurrencyUnit currency, Iterable<Money> monies) {
315
        return Money.zero(currency).plus(monies);
316
    }
317
318
    //-----------------------------------------------------------------------
319
    /**
320
     * Parses an instance of {@code Money} from a string.
321
     * <p>
322
     * The string format is '$currencyCode $amount' where there may be
323
     * zero to many spaces between the two parts.
324
     * The currency code must be a valid three letter currency.
325
     * The amount must match the regular expression {@code [+-]?[0-9]*[.]?[0-9]*}.
326
     * The spaces and numbers must be ASCII characters.
327
     * This matches the output from {@link #toString()}.
328
     * <p>
329
     * For example, {@code parse("USD 25")} creates the instance {@code USD 25.00}
330
     * while {@code parse("USD 25.95")} creates the instance {@code USD 25.95}.
331
     *
332
     * @param moneyStr  the money string to parse, not null
333
     * @return the parsed instance, never null
334
     * @throws IllegalArgumentException if the string is malformed
335
     * @throws ArithmeticException if the amount is too large
336
     */
337
    @FromString
338
    public static Money parse(String moneyStr) {
339
        return Money.of(BigMoney.parse(moneyStr));
340
    }
341
342
    //-----------------------------------------------------------------------
343
    /**
344
     * Private no-args constructor, for use as JPA Embeddable (for example).
345
     */
346
    @SuppressWarnings("unused")
347
    private Money() {
348
        this.money = null;
349
    }
350
351
    /**
352
     * Constructor, creating a new monetary instance.
353
     *
354
     * @param money  the underlying money, not null
355
     */
356
    Money(BigMoney money) {
357
        assert money != null : "Joda-Money bug: BigMoney must not be null";
358
        assert money.isCurrencyScale() : "Joda-Money bug: Only currency scale is valid for Money";
359
        this.money = money;
360
    }
361
362
    /**
363
     * Block malicious data streams.
364
     *
365
     * @param ois  the input stream, not null
366
     * @throws InvalidObjectException if an error occurs
367
     */
368
    private void readObject(ObjectInputStream ois) throws InvalidObjectException {
369
        throw new InvalidObjectException("Serialization delegate required");
370
    }
371
372
    /**
373
     * Uses a serialization delegate.
374
     *
375
     * @return the replacing object, never null
376
     */
377
    private Object writeReplace() {
378
        return new Ser(Ser.MONEY, this);
379
    }
380
381
    //-----------------------------------------------------------------------
382
    /**
383
     * Returns a new {@code Money}, returning {@code this} if possible.
384
     * <p>
385
     * This instance is immutable and unaffected by this method.
386
     *
387
     * @param newInstance  the new money to use, not null
388
     * @return the new instance, never null
389
     */
390
    private Money with(BigMoney newInstance) {
391
        if (money.equals(newInstance)) {
392
            return this;
393
        }
394
        return new Money(newInstance);
395
    }
396
397
    //-----------------------------------------------------------------------
398
    /**
399
     * Gets the currency.
400
     *
401
     * @return the currency, never null
402
     */
403
    public CurrencyUnit getCurrencyUnit() {
404
        return money.getCurrencyUnit();
405
    }
406
407
    //-----------------------------------------------------------------------
408
    /**
409
     * Returns a copy of this monetary value with the specified currency.
410
     * <p>
411
     * The returned instance will have the specified currency and the amount
412
     * from this instance. If the scale differs between the currencies such
413
     * that rounding would be required, then an exception is thrown.
414
     * <p>
415
     * This instance is immutable and unaffected by this method.
416
     *
417
     * @param currency  the currency to use, not null
418
     * @return the new instance with the input currency set, never null
419
     * @throws ArithmeticException if the scale of the new currency is less than
420
     *  the scale of this currency
421
     */
422
    public Money withCurrencyUnit(CurrencyUnit currency) {
423
        return withCurrencyUnit(currency, RoundingMode.UNNECESSARY);
424
    }
425
426
    /**
427
     * Returns a copy of this monetary value with the specified currency.
428
     * <p>
429
     * The returned instance will have the specified currency and the amount
430
     * from this instance. If the number of decimal places differs between the
431
     * currencies, then the amount may be rounded.
432
     * <p>
433
     * This instance is immutable and unaffected by this method.
434
     *
435
     * @param currency  the currency to use, not null
436
     * @param roundingMode  the rounding mode to use to bring the decimal places back in line, not null
437
     * @return the new instance with the input currency set, never null
438
     * @throws ArithmeticException if the rounding fails
439
     */
440
    public Money withCurrencyUnit(CurrencyUnit currency, RoundingMode roundingMode) {
441
        return with(money.withCurrencyUnit(currency).withCurrencyScale(roundingMode));
442
    }
443
444
    //-----------------------------------------------------------------------
445
    /**
446
     * Gets the scale of the {@code BigDecimal} amount.
447
     * <p>
448
     * The scale has the same meaning as in {@link BigDecimal}.
449
     * Positive values represent the number of decimal places in use.
450
     * For example, a scale of 2 means that the money will have two decimal places
451
     * such as 'USD 43.25'.
452
     * <p>
453
     * For {@code Money}, the scale is fixed and always matches that of the currency.
454
     *
455
     * @return the scale in use, typically 2 but could be 0, 1 and 3
456
     */
457
    public int getScale() {
458
        return money.getScale();
459
    }
460
461
    //-----------------------------------------------------------------------
462
    /**
463
     * Gets the amount.
464
     * <p>
465
     * This returns the value of the money as a {@code BigDecimal}.
466
     * The scale will be the scale of this money.
467
     *
468
     * @return the amount, never null
469
     */
470
    public BigDecimal getAmount() {
471
        return money.getAmount();
472
    }
473
474
    /**
475
     * Gets the amount in major units as a {@code BigDecimal} with scale 0.
476
     * <p>
477
     * This returns the monetary amount in terms of the major units of the currency,
478
     * truncating the amount if necessary.
479
     * For example, 'EUR 2.35' will return 2, and 'BHD -1.345' will return -1.
480
     * <p>
481
     * This is returned as a {@code BigDecimal} rather than a {@code BigInteger}.
482
     * This is to allow further calculations to be performed on the result.
483
     * Should you need a {@code BigInteger}, simply call {@link BigDecimal#toBigInteger()}.
484
     *
485
     * @return the major units part of the amount, never null
486
     */
487
    public BigDecimal getAmountMajor() {
488
        return money.getAmountMajor();
489
    }
490
491
    /**
492
     * Gets the amount in major units as a {@code long}.
493
     * <p>
494
     * This returns the monetary amount in terms of the major units of the currency,
495
     * truncating the amount if necessary.
496
     * For example, 'EUR 2.35' will return 2, and 'BHD -1.345' will return -1.
497
     *
498
     * @return the major units part of the amount
499
     * @throws ArithmeticException if the amount is too large for a {@code long}
500
     */
501
    public long getAmountMajorLong() {
502
        return money.getAmountMajorLong();
503
    }
504
505
    /**
506
     * Gets the amount in major units as an {@code int}.
507
     * <p>
508
     * This returns the monetary amount in terms of the major units of the currency,
509
     * truncating the amount if necessary.
510
     * For example, 'EUR 2.35' will return 2, and 'BHD -1.345' will return -1.
511
     *
512
     * @return the major units part of the amount
513
     * @throws ArithmeticException if the amount is too large for an {@code int}
514
     */
515
    public int getAmountMajorInt() {
516
        return money.getAmountMajorInt();
517
    }
518
519
    /**
520
     * Gets the amount in minor units as a {@code BigDecimal} with scale 0.
521
     * <p>
522
     * This returns the monetary amount in terms of the minor units of the currency,
523
     * truncating the amount if necessary.
524
     * For example, 'EUR 2.35' will return 235, and 'BHD -1.345' will return -1345.
525
     * <p>
526
     * This is returned as a {@code BigDecimal} rather than a {@code BigInteger}.
527
     * This is to allow further calculations to be performed on the result.
528
     * Should you need a {@code BigInteger}, simply call {@link BigDecimal#toBigInteger()}.
529
     *
530
     * @return the minor units part of the amount, never null
531
     */
532
    public BigDecimal getAmountMinor() {
533
        return money.getAmountMinor();
534
    }
535
536
    /**
537
     * Gets the amount in minor units as a {@code long}.
538
     * <p>
539
     * This returns the monetary amount in terms of the minor units of the currency,
540
     * truncating the amount if necessary.
541
     * For example, 'EUR 2.35' will return 235, and 'BHD -1.345' will return -1345.
542
     *
543
     * @return the minor units part of the amount
544
     * @throws ArithmeticException if the amount is too large for a {@code long}
545
     */
546
    public long getAmountMinorLong() {
547
        return money.getAmountMinorLong();
548
    }
549
550
    /**
551
     * Gets the amount in minor units as an {@code int}.
552
     * <p>
553
     * This returns the monetary amount in terms of the minor units of the currency,
554
     * truncating the amount if necessary.
555
     * For example, 'EUR 2.35' will return 235, and 'BHD -1.345' will return -1345.
556
     *
557
     * @return the minor units part of the amount
558
     * @throws ArithmeticException if the amount is too large for an {@code int}
559
     */
560
    public int getAmountMinorInt() {
561
        return money.getAmountMinorInt();
562
    }
563
564
    /**
565
     * Gets the minor part of the amount.
566
     * <p>
567
     * This return the minor unit part of the monetary amount.
568
     * This is defined as the amount in minor units excluding major units.
569
     * <p>
570
     * For example, EUR has a scale of 2, so the minor part is always between 0 and 99
571
     * for positive amounts, and 0 and -99 for negative amounts.
572
     * Thus 'EUR 2.35' will return 35, and 'EUR -1.34' will return -34.
573
     *
574
     * @return the minor part of the amount, negative if the amount is negative
575
     */
576
    public int getMinorPart() {
577
        return money.getMinorPart();
578
    }
579
580
    //-----------------------------------------------------------------------
581
    /**
582
     * Checks if the amount is zero.
583
     *
584
     * @return true if the amount is zero
585
     */
586
    public boolean isZero() {
587
        return money.isZero();
588
    }
589
590
    /**
591
     * Checks if the amount is greater than zero.
592
     *
593
     * @return true if the amount is greater than zero
594
     */
595
    public boolean isPositive() {
596
        return money.isPositive();
597
    }
598
599
    /**
600
     * Checks if the amount is zero or greater.
601
     *
602
     * @return true if the amount is zero or greater
603
     */
604
    public boolean isPositiveOrZero() {
605
        return money.isPositiveOrZero();
606
    }
607
608
    /**
609
     * Checks if the amount is less than zero.
610
     *
611
     * @return true if the amount is less than zero
612
     */
613
    public boolean isNegative() {
614
        return money.isNegative();
615
    }
616
617
    /**
618
     * Checks if the amount is zero or less.
619
     *
620
     * @return true if the amount is zero or less
621
     */
622
    public boolean isNegativeOrZero() {
623
        return money.isNegativeOrZero();
624
    }
625
626
    //-----------------------------------------------------------------------
627
    /**
628
     * Returns a copy of this monetary value with the specified amount.
629
     * <p>
630
     * The returned instance will have this currency and the new amount.
631
     * No rounding is performed on the amount to be added, so it must have a
632
     * scale compatible with the currency.
633
     * <p>
634
     * This instance is immutable and unaffected by this method.
635
     *
636
     * @param amount  the monetary amount to set in the returned instance, not null
637
     * @return the new instance with the input amount set, never null
638
     * @throws ArithmeticException if the scale of the amount is too large
639
     */
640
    public Money withAmount(BigDecimal amount) {
641
        return withAmount(amount, RoundingMode.UNNECESSARY);
642
    }
643
644
    /**
645
     * Returns a copy of this monetary value with the specified amount.
646
     * <p>
647
     * The returned instance will have this currency and the new amount.
648
     * If the scale of the {@code BigDecimal} needs to be adjusted, then
649
     * it will be rounded using the specified mode.
650
     * <p>
651
     * This instance is immutable and unaffected by this method.
652
     *
653
     * @param amount  the monetary amount to set in the returned instance, not null
654
     * @param roundingMode  the rounding mode to adjust the scale, not null
655
     * @return the new instance with the input amount set, never null
656
     */
657
    public Money withAmount(BigDecimal amount, RoundingMode roundingMode) {
658
        return with(money.withAmount(amount).withCurrencyScale(roundingMode));
659
    }
660
661
    /**
662
     * Returns a copy of this monetary value with the specified amount using a well-defined
663
     * conversion from a {@code double}.
664
     * <p>
665
     * The returned instance will have this currency and the new amount.
666
     * No rounding is performed on the amount to be added, so it must have a
667
     * scale compatible with the currency.
668
     * <p>
669
     * The amount is converted via {@link BigDecimal#valueOf(double)} which yields
670
     * the most expected answer for most programming scenarios.
671
     * Any {@code double} literal in code will be converted to
672
     * exactly the same BigDecimal with the same scale.
673
     * For example, the literal '1.45d' will be converted to '1.45'.
674
     * <p>
675
     * This instance is immutable and unaffected by this method.
676
     *
677
     * @param amount  the monetary amount to set in the returned instance, not null
678
     * @return the new instance with the input amount set, never null
679
     * @throws ArithmeticException if the scale of the amount is too large
680
     */
681
    public Money withAmount(double amount) {
682
        return withAmount(amount, RoundingMode.UNNECESSARY);
683
    }
684
685
    /**
686
     * Returns a copy of this monetary value with the specified amount using a well-defined
687
     * conversion from a {@code double}.
688
     * <p>
689
     * The returned instance will have this currency and the new amount.
690
     * If the scale of the {@code BigDecimal} needs to be adjusted, then
691
     * it will be rounded using the specified mode.
692
     * <p>
693
     * The amount is converted via {@link BigDecimal#valueOf(double)} which yields
694
     * the most expected answer for most programming scenarios.
695
     * Any {@code double} literal in code will be converted to
696
     * exactly the same BigDecimal with the same scale.
697
     * For example, the literal '1.45d' will be converted to '1.45'.
698
     * <p>
699
     * This instance is immutable and unaffected by this method.
700
     *
701
     * @param amount  the monetary amount to set in the returned instance, not null
702
     * @param roundingMode  the rounding mode to adjust the scale, not null
703
     * @return the new instance with the input amount set, never null
704
     */
705
    public Money withAmount(double amount, RoundingMode roundingMode) {
706
        return with(money.withAmount(amount).withCurrencyScale(roundingMode));
707
    }
708
709
    //-----------------------------------------------------------------------
710
    /**
711
     * Returns a copy of this monetary value with a collection of monetary amounts added.
712
     * <p>
713
     * This adds the specified amounts to this monetary amount, returning a new object.
714
     * The amounts must be in the same currency.
715
     * <p>
716
     * This instance is immutable and unaffected by this method.
717
     *
718
     * @param moniesToAdd  the monetary values to add, no null elements, not null
719
     * @return the new instance with the input amounts added, never null
720
     * @throws CurrencyMismatchException if the currencies differ
721
     */
722
    public Money plus(Iterable<Money> moniesToAdd) {
723
        return with(money.plus(moniesToAdd));
724
    }
725
726
    //-----------------------------------------------------------------------
727
    /**
728
     * Returns a copy of this monetary value with the amount added.
729
     * <p>
730
     * This adds the specified amount to this monetary amount, returning a new object.
731
     * The amount added must be in the same currency.
732
     * <p>
733
     * The addition has no rounding issues and is always accurate.
734
     * For example,'USD 25.95' plus 'USD 3.02' will 'USD 28.97'.
735
     * <p>
736
     * This instance is immutable and unaffected by this method.
737
     *
738
     * @param moneyToAdd  the monetary value to add, not null
739
     * @return the new instance with the input amount added, never null
740
     * @throws CurrencyMismatchException if the currencies differ
741
     */
742
    public Money plus(Money moneyToAdd) {
743
        return with(money.plus(moneyToAdd));
744
    }
745
746
    /**
747
     * Returns a copy of this monetary value with the amount added.
748
     * <p>
749
     * This adds the specified amount to this monetary amount, returning a new object.
750
     * No rounding is performed on the amount to be added, so it must have a
751
     * scale compatible with the currency.
752
     * <p>
753
     * This instance is immutable and unaffected by this method.
754
     *
755
     * @param amountToAdd  the monetary value to add, not null
756
     * @return the new instance with the input amount added, never null
757
     * @throws ArithmeticException if the scale of the amount is too large
758
     */
759
    public Money plus(BigDecimal amountToAdd) {
760
        return plus(amountToAdd, RoundingMode.UNNECESSARY);
761
    }
762
763
    /**
764
     * Returns a copy of this monetary value with the amount added.
765
     * <p>
766
     * This adds the specified amount to this monetary amount, returning a new object.
767
     * If the amount to add exceeds the scale of the currency, then the
768
     * rounding mode will be used to adjust the result.
769
     * <p>
770
     * This instance is immutable and unaffected by this method.
771
     *
772
     * @param amountToAdd  the monetary value to add, not null
773
     * @param roundingMode  the rounding mode to use, not null
774
     * @return the new instance with the input amount added, never null
775
     */
776
    public Money plus(BigDecimal amountToAdd, RoundingMode roundingMode) {
777
        return with(money.plusRetainScale(amountToAdd, roundingMode));
778
    }
779
780
    /**
781
     * Returns a copy of this monetary value with the amount added.
782
     * <p>
783
     * This adds the specified amount to this monetary amount, returning a new object.
784
     * No rounding is performed on the amount to be added, so it must have a
785
     * scale compatible with the currency.
786
     * <p>
787
     * The amount is converted via {@link BigDecimal#valueOf(double)} which yields
788
     * the most expected answer for most programming scenarios.
789
     * Any {@code double} literal in code will be converted to
790
     * exactly the same BigDecimal with the same scale.
791
     * For example, the literal '1.45d' will be converted to '1.45'.
792
     * <p>
793
     * This instance is immutable and unaffected by this method.
794
     *
795
     * @param amountToAdd  the monetary value to add, not null
796
     * @return the new instance with the input amount added, never null
797
     * @throws ArithmeticException if the scale of the amount is too large
798
     */
799
    public Money plus(double amountToAdd) {
800
        return plus(amountToAdd, RoundingMode.UNNECESSARY);
801
    }
802
803
    /**
804
     * Returns a copy of this monetary value with the amount added.
805
     * <p>
806
     * This adds the specified amount to this monetary amount, returning a new object.
807
     * If the amount to add exceeds the scale of the currency, then the
808
     * rounding mode will be used to adjust the result.
809
     * <p>
810
     * The amount is converted via {@link BigDecimal#valueOf(double)} which yields
811
     * the most expected answer for most programming scenarios.
812
     * Any {@code double} literal in code will be converted to
813
     * exactly the same BigDecimal with the same scale.
814
     * For example, the literal '1.45d' will be converted to '1.45'.
815
     * <p>
816
     * This instance is immutable and unaffected by this method.
817
     *
818
     * @param amountToAdd  the monetary value to add, not null
819
     * @param roundingMode  the rounding mode to use, not null
820
     * @return the new instance with the input amount added, never null
821
     */
822
    public Money plus(double amountToAdd, RoundingMode roundingMode) {
823
        return with(money.plusRetainScale(amountToAdd, roundingMode));
824
    }
825
826
    /**
827
     * Returns a copy of this monetary value with the amount in major units added.
828
     * <p>
829
     * This adds an amount in major units, leaving the minor units untouched.
830
     * For example, USD 23.45 plus 138 gives USD 161.45.
831
     * <p>
832
     * This instance is immutable and unaffected by this method.
833
     *
834
     * @param amountToAdd  the monetary value to add, not null
835
     * @return the new instance with the input amount added, never null
836
     */
837
    public Money plusMajor(long amountToAdd) {
838
        return with(money.plusMajor(amountToAdd));
839
    }
840
841
    /**
842
     * Returns a copy of this monetary value with the amount in minor units added.
843
     * <p>
844
     * This adds an amount in minor units.
845
     * For example, USD 23.45 plus 138 gives USD 24.83.
846
     * <p>
847
     * This instance is immutable and unaffected by this method.
848
     *
849
     * @param amountToAdd  the monetary value to add, not null
850
     * @return the new instance with the input amount added, never null
851
     */
852
    public Money plusMinor(long amountToAdd) {
853
        return with(money.plusMinor(amountToAdd));
854
    }
855
856
    //-----------------------------------------------------------------------
857
    /**
858
     * Returns a copy of this monetary value with a collection of monetary amounts subtracted.
859
     * <p>
860
     * This subtracts the specified amounts from this monetary amount, returning a new object.
861
     * The amounts must be in the same currency.
862
     * <p>
863
     * This instance is immutable and unaffected by this method.
864
     *
865
     * @param moniesToSubtract  the monetary values to subtract, no null elements, not null
866
     * @return the new instance with the input amounts subtracted, never null
867
     * @throws CurrencyMismatchException if the currencies differ
868
     */
869
    public Money minus(Iterable<Money> moniesToSubtract) {
870
        return with(money.minus(moniesToSubtract));
871
    }
872
873
    //-----------------------------------------------------------------------
874
    /**
875
     * Returns a copy of this monetary value with the amount subtracted.
876
     * <p>
877
     * This subtracts the specified amount from this monetary amount, returning a new object.
878
     * The amount subtracted must be in the same currency.
879
     * <p>
880
     * The subtraction has no rounding issues and is always accurate.
881
     * For example,'USD 25.95' minus 'USD 3.02' will 'USD 22.93'.
882
     * <p>
883
     * This instance is immutable and unaffected by this method.
884
     *
885
     * @param moneyToSubtract  the monetary value to subtract, not null
886
     * @return the new instance with the input amount subtracted, never null
887
     * @throws CurrencyMismatchException if the currencies differ
888
     */
889
    public Money minus(Money moneyToSubtract) {
890
        return with(money.minus(moneyToSubtract));
891
    }
892
893
    /**
894
     * Returns a copy of this monetary value with the amount subtracted.
895
     * <p>
896
     * This subtracts the specified amount from this monetary amount, returning a new object.
897
     * No rounding is performed on the amount to be subtracted, so it must have a
898
     * scale compatible with the currency.
899
     * <p>
900
     * This instance is immutable and unaffected by this method.
901
     *
902
     * @param amountToSubtract  the monetary value to subtract, not null
903
     * @return the new instance with the input amount subtracted, never null
904
     * @throws ArithmeticException if the scale of the amount is too large
905
     */
906
    public Money minus(BigDecimal amountToSubtract) {
907
        return minus(amountToSubtract, RoundingMode.UNNECESSARY);
908
    }
909
910
    /**
911
     * Returns a copy of this monetary value with the amount subtracted.
912
     * <p>
913
     * This subtracts the specified amount from this monetary amount, returning a new object.
914
     * If the amount to subtract exceeds the scale of the currency, then the
915
     * rounding mode will be used to adjust the result.
916
     * <p>
917
     * This instance is immutable and unaffected by this method.
918
     *
919
     * @param amountToSubtract  the monetary value to subtract, not null
920
     * @param roundingMode  the rounding mode to use, not null
921
     * @return the new instance with the input amount subtracted, never null
922
     */
923
    public Money minus(BigDecimal amountToSubtract, RoundingMode roundingMode) {
924
        return with(money.minusRetainScale(amountToSubtract, roundingMode));
925
    }
926
927
    /**
928
     * Returns a copy of this monetary value with the amount subtracted.
929
     * <p>
930
     * This subtracts the specified amount from this monetary amount, returning a new object.
931
     * No rounding is performed on the amount to be subtracted, so it must have a
932
     * scale compatible with the currency.
933
     * <p>
934
     * The amount is converted via {@link BigDecimal#valueOf(double)} which yields
935
     * the most expected answer for most programming scenarios.
936
     * Any {@code double} literal in code will be converted to
937
     * exactly the same BigDecimal with the same scale.
938
     * For example, the literal '1.45d' will be converted to '1.45'.
939
     * <p>
940
     * This instance is immutable and unaffected by this method.
941
     *
942
     * @param amountToSubtract  the monetary value to subtract, not null
943
     * @return the new instance with the input amount subtracted, never null
944
     * @throws ArithmeticException if the scale of the amount is too large
945
     */
946
    public Money minus(double amountToSubtract) {
947
        return minus(amountToSubtract, RoundingMode.UNNECESSARY);
948
    }
949
950
    /**
951
     * Returns a copy of this monetary value with the amount subtracted.
952
     * <p>
953
     * This subtracts the specified amount from this monetary amount, returning a new object.
954
     * If the amount to subtract exceeds the scale of the currency, then the
955
     * rounding mode will be used to adjust the result.
956
     * <p>
957
     * The amount is converted via {@link BigDecimal#valueOf(double)} which yields
958
     * the most expected answer for most programming scenarios.
959
     * Any {@code double} literal in code will be converted to
960
     * exactly the same BigDecimal with the same scale.
961
     * For example, the literal '1.45d' will be converted to '1.45'.
962
     * <p>
963
     * This instance is immutable and unaffected by this method.
964
     *
965
     * @param amountToSubtract  the monetary value to subtract, not null
966
     * @param roundingMode  the rounding mode to use, not null
967
     * @return the new instance with the input amount subtracted, never null
968
     */
969
    public Money minus(double amountToSubtract, RoundingMode roundingMode) {
970
        return with(money.minusRetainScale(amountToSubtract, roundingMode));
971
    }
972
973
    /**
974
     * Returns a copy of this monetary value with the amount in major units subtracted.
975
     * <p>
976
     * This subtracts an amount in major units, leaving the minor units untouched.
977
     * For example, USD 23.45 minus 138 gives USD -114.55.
978
     * <p>
979
     * This instance is immutable and unaffected by this method.
980
     *
981
     * @param amountToSubtract  the monetary value to subtract, not null
982
     * @return the new instance with the input amount subtracted, never null
983
     */
984
    public Money minusMajor(long amountToSubtract) {
985
        return with(money.minusMajor(amountToSubtract));
986
    }
987
988
    /**
989
     * Returns a copy of this monetary value with the amount in minor units subtracted.
990
     * <p>
991
     * This subtracts an amount in minor units.
992
     * For example, USD 23.45 minus 138 gives USD 22.07.
993
     * <p>
994
     * This instance is immutable and unaffected by this method.
995
     *
996
     * @param amountToSubtract  the monetary value to subtract, not null
997
     * @return the new instance with the input amount subtracted, never null
998
     */
999
    public Money minusMinor(long amountToSubtract) {
1000
        return with(money.minusMinor(amountToSubtract));
1001
    }
1002
1003
    //-----------------------------------------------------------------------
1004
    /**
1005
     * Returns a copy of this monetary value multiplied by the specified value.
1006
     * <p>
1007
     * This takes this amount and multiplies it by the specified value, rounding
1008
     * the result is rounded as specified.
1009
     * <p>
1010
     * This instance is immutable and unaffected by this method.
1011
     *
1012
     * @param valueToMultiplyBy  the scalar value to multiply by, not null
1013
     * @param roundingMode  the rounding mode to use to bring the decimal places back in line, not null
1014
     * @return the new multiplied instance, never null
1015
     * @throws ArithmeticException if the rounding fails
1016
     */
1017
    public Money multipliedBy(BigDecimal valueToMultiplyBy, RoundingMode roundingMode) {
1018
        return with(money.multiplyRetainScale(valueToMultiplyBy, roundingMode));
1019
    }
1020
1021
    /**
1022
     * Returns a copy of this monetary value multiplied by the specified value.
1023
     * <p>
1024
     * This takes this amount and multiplies it by the specified value, rounding
1025
     * the result is rounded as specified.
1026
     * <p>
1027
     * The amount is converted via {@link BigDecimal#valueOf(double)} which yields
1028
     * the most expected answer for most programming scenarios.
1029
     * Any {@code double} literal in code will be converted to
1030
     * exactly the same BigDecimal with the same scale.
1031
     * For example, the literal '1.45d' will be converted to '1.45'.
1032
     * <p>
1033
     * This instance is immutable and unaffected by this method.
1034
     *
1035
     * @param valueToMultiplyBy  the scalar value to multiply by, not null
1036
     * @param roundingMode  the rounding mode to use to bring the decimal places back in line, not null
1037
     * @return the new multiplied instance, never null
1038
     * @throws ArithmeticException if the rounding fails
1039
     */
1040
    public Money multipliedBy(double valueToMultiplyBy, RoundingMode roundingMode) {
1041
        return with(money.multiplyRetainScale(valueToMultiplyBy, roundingMode));
1042
    }
1043
1044
    /**
1045
     * Returns a copy of this monetary value multiplied by the specified value.
1046
     * <p>
1047
     * This takes this amount and multiplies it by the specified value.
1048
     * <p>
1049
     * This instance is immutable and unaffected by this method.
1050
     *
1051
     * @param valueToMultiplyBy  the scalar value to multiply by, not null
1052
     * @return the new multiplied instance, never null
1053
     */
1054
    public Money multipliedBy(long valueToMultiplyBy) {
1055
        return with(money.multipliedBy(valueToMultiplyBy));
1056
    }
1057
1058
    //-----------------------------------------------------------------------
1059
    /**
1060
     * Returns a copy of this monetary value divided by the specified value.
1061
     * <p>
1062
     * This takes this amount and divides it by the specified value, rounding
1063
     * the result is rounded as specified.
1064
     * <p>
1065
     * This instance is immutable and unaffected by this method.
1066
     *
1067
     * @param valueToDivideBy  the scalar value to divide by, not null
1068
     * @param roundingMode  the rounding mode to use, not null
1069
     * @return the new divided instance, never null
1070
     * @throws ArithmeticException if dividing by zero
1071
     * @throws ArithmeticException if the rounding fails
1072
     */
1073
    public Money dividedBy(BigDecimal valueToDivideBy, RoundingMode roundingMode) {
1074
        return with(money.dividedBy(valueToDivideBy, roundingMode));
1075
    }
1076
1077
    /**
1078
     * Returns a copy of this monetary value divided by the specified value.
1079
     * <p>
1080
     * This takes this amount and divides it by the specified value, rounding
1081
     * the result is rounded as specified.
1082
     * <p>
1083
     * The amount is converted via {@link BigDecimal#valueOf(double)} which yields
1084
     * the most expected answer for most programming scenarios.
1085
     * Any {@code double} literal in code will be converted to
1086
     * exactly the same BigDecimal with the same scale.
1087
     * For example, the literal '1.45d' will be converted to '1.45'.
1088
     * <p>
1089
     * This instance is immutable and unaffected by this method.
1090
     *
1091
     * @param valueToDivideBy  the scalar value to divide by, not null
1092
     * @param roundingMode  the rounding mode to use, not null
1093
     * @return the new divided instance, never null
1094
     * @throws ArithmeticException if dividing by zero
1095
     * @throws ArithmeticException if the rounding fails
1096
     */
1097
    public Money dividedBy(double valueToDivideBy, RoundingMode roundingMode) {
1098
        return with(money.dividedBy(valueToDivideBy, roundingMode));
1099
    }
1100
1101
    /**
1102
     * Returns a copy of this monetary value divided by the specified value.
1103
     * <p>
1104
     * This takes this amount and divides it by the specified value, rounding
1105
     * the result is rounded as specified.
1106
     * <p>
1107
     * This instance is immutable and unaffected by this method.
1108
     *
1109
     * @param valueToDivideBy  the scalar value to divide by, not null
1110
     * @param roundingMode  the rounding mode to use, not null
1111
     * @return the new divided instance, never null
1112
     * @throws ArithmeticException if dividing by zero
1113
     * @throws ArithmeticException if the rounding fails
1114
     */
1115
    public Money dividedBy(long valueToDivideBy, RoundingMode roundingMode) {
1116
        return with(money.dividedBy(valueToDivideBy, roundingMode));
1117
    }
1118
1119
    //-----------------------------------------------------------------------
1120
    /**
1121
     * Returns a copy of this monetary value with the amount negated.
1122
     * <p>
1123
     * This instance is immutable and unaffected by this method.
1124
     *
1125
     * @return the new instance with the amount negated, never null
1126
     */
1127
    public Money negated() {
1128
        return with(money.negated());
1129
    }
1130
1131
    /**
1132
     * Returns a copy of this monetary value with a positive amount.
1133
     * <p>
1134
     * This instance is immutable and unaffected by this method.
1135
     *
1136
     * @return the new instance with the amount converted to be positive, never null
1137
     */
1138
    public Money abs() {
1139
        return (isNegative() ? negated() : this);
1140
    }
1141
1142
    //-----------------------------------------------------------------------
1143
    /**
1144
     * Returns a copy of this monetary value rounded to the specified scale without
1145
     * changing the current scale.
1146
     * <p>
1147
     * Scale has the same meaning as in {@link BigDecimal}.
1148
     * A scale of 2 means round to 2 decimal places.
1149
     * <ul>
1150
     * <li>Rounding 'EUR 45.23' to a scale of -1 returns 40.00 or 50.00 depending on the rounding mode.
1151
     * <li>Rounding 'EUR 45.23' to a scale of 0 returns 45.00 or 46.00 depending on the rounding mode.
1152
     * <li>Rounding 'EUR 45.23' to a scale of 1 returns 45.20 or 45.30 depending on the rounding mode.
1153
     * <li>Rounding 'EUR 45.23' to a scale of 2 has no effect (it already has that scale).
1154
     * <li>Rounding 'EUR 45.23' to a scale of 3 has no effect (the scale is not increased).
1155
     * </ul>
1156
     * <p>
1157
     * This instance is immutable and unaffected by this method.
1158
     *
1159
     * @param scale  the new scale
1160
     * @param roundingMode  the rounding mode to use, not null
1161
     * @return the new instance with the amount converted to be positive, never null
1162
     * @throws ArithmeticException if the rounding fails
1163
     */
1164
    public Money rounded(int scale, RoundingMode roundingMode) {
1165
        return with(money.rounded(scale, roundingMode));
1166
    }
1167
1168
    //-----------------------------------------------------------------------
1169
    /**
1170
     * Returns a copy of this monetary value converted into another currency
1171
     * using the specified conversion rate, with a rounding mode used to adjust
1172
     * the decimal places in the result.
1173
     * <p>
1174
     * This instance is immutable and unaffected by this method.
1175
     *
1176
     * @param currency  the new currency, not null
1177
     * @param conversionMultipler  the conversion factor between the currencies, not null
1178
     * @param roundingMode  the rounding mode to use to bring the decimal places back in line, not null
1179
     * @return the new multiplied instance, never null
1180
     * @throws IllegalArgumentException if the currency is the same as this currency
1181
     * @throws IllegalArgumentException if the conversion multiplier is negative
1182
     * @throws ArithmeticException if the rounding fails
1183
     */
1184
    public Money convertedTo(CurrencyUnit currency, BigDecimal conversionMultipler, RoundingMode roundingMode) {
1185
        return with(money.convertedTo(currency, conversionMultipler).withCurrencyScale(roundingMode));
1186
    }
1187
1188
    //-----------------------------------------------------------------------
1189
    /**
1190
     * Implements the {@code BigMoneyProvider} interface, returning a
1191
     * {@code BigMoney} instance with the same currency, amount and scale.
1192
     *
1193
     * @return the money instance, never null
1194
     */
1195
    @Override
1196
    public BigMoney toBigMoney() {
1197
        return money;
1198
    }
1199
1200
    //-----------------------------------------------------------------------
1201
    /**
1202
     * Checks if this instance and the specified instance have the same currency.
1203
     *
1204
     * @param other  the money to check, not null
1205
     * @return true if they have the same currency
1206
     */
1207
    public boolean isSameCurrency(BigMoneyProvider other) {
1208
        return money.isSameCurrency(other);
1209
    }
1210
1211
    //-----------------------------------------------------------------------
1212
    /**
1213
     * Compares this monetary value to another.
1214
     * <p>
1215
     * This allows {@code Money} to be compared to any {@code BigMoneyProvider}.
1216
     * Scale is ignored in the comparison.
1217
     * The compared values must be in the same currency.
1218
     *
1219
     * @param other  the other monetary value, not null
1220
     * @return -1 if this is less than , 0 if equal, 1 if greater than
1221
     * @throws CurrencyMismatchException if the currencies differ
1222
     */
1223
    @Override
1224
    public int compareTo(BigMoneyProvider other) {
1225
        return money.compareTo(other);
1226
    }
1227
1228
    /**
1229
     * Checks if this monetary value is equal to another.
1230
     * <p>
1231
     * This allows {@code Money} to be compared to any {@code BigMoneyProvider}.
1232
     * Scale is ignored, so 'USD 30.00' and 'USD 30' are equal.
1233
     * The compared values must be in the same currency.
1234
     *
1235
     * @param other  the other monetary value, not null
1236
     * @return true is this is greater than the specified monetary value
1237
     * @throws CurrencyMismatchException if the currencies differ
1238
     * @see #equals(Object)
1239
     */
1240
    public boolean isEqual(BigMoneyProvider other) {
1241
        return money.isEqual(other);
1242
    }
1243
1244
    /**
1245
     * Checks if this monetary value is greater than another.
1246
     * <p>
1247
     * This allows {@code Money} to be compared to any {@code BigMoneyProvider}.
1248
     * Scale is ignored in the comparison.
1249
     * The compared values must be in the same currency.
1250
     *
1251
     * @param other  the other monetary value, not null
1252
     * @return true is this is greater than the specified monetary value
1253
     * @throws CurrencyMismatchException if the currencies differ
1254
     */
1255
    public boolean isGreaterThan(BigMoneyProvider other) {
1256
        return money.isGreaterThan(other);
1257
    }
1258
1259
    /**
1260
     * Checks if this monetary value is greater than or equal to another.
1261
     * <p>
1262
     * This allows {@code Money} to be compared to any {@code BigMoneyProvider}.
1263
     * Scale is ignored in the comparison.
1264
     * The compared values must be in the same currency.
1265
     *
1266
     * @param other  the other monetary value, not null
1267
     * @return true is this is greater than or equal to the specified monetary value
1268
     * @throws CurrencyMismatchException if the currencies differ
1269
     */
1270
    public boolean isGreaterThanOrEqual(BigMoneyProvider other) {
1271
        return money.isGreaterThanOrEqual(other);
1272
    }
1273
1274
    /**
1275
     * Checks if this monetary value is less than another.
1276
     * <p>
1277
     * This allows {@code Money} to be compared to any {@code BigMoneyProvider}.
1278
     * Scale is ignored in the comparison.
1279
     * The compared values must be in the same currency.
1280
     *
1281
     * @param other  the other monetary value, not null
1282
     * @return true is this is less than the specified monetary value
1283
     * @throws CurrencyMismatchException if the currencies differ
1284
     */
1285
    public boolean isLessThan(BigMoneyProvider other) {
1286
        return money.isLessThan(other);
1287
    }
1288
1289
    /**
1290
     * Checks if this monetary value is less than or equal to another.
1291
     * <p>
1292
     * This allows {@code Money} to be compared to any {@code BigMoneyProvider}.
1293
     * Scale is ignored in the comparison.
1294
     * The compared values must be in the same currency.
1295
     *
1296
     * @param other  the other monetary value, not null
1297
     * @return true is this is less than or equal to the specified monetary value
1298
     * @throws CurrencyMismatchException if the currencies differ
1299
     */
1300
    public boolean isLessThanOrEqual(BigMoneyProvider other) {
1301
        return money.isLessThanOrEqual(other);
1302
    }
1303
1304
    //-----------------------------------------------------------------------
1305
    /**
1306
     * Checks if this monetary value equals another.
1307
     * <p>
1308
     * The comparison takes into account the scale.
1309
     * The compared values must be in the same currency.
1310
     *
1311
     * @param other  the other object to compare to, not null
1312
     * @return true if this instance equals the other instance
1313
     */
1314
    @Override
1315
    public boolean equals(Object other) {
1316
        if (this == other) {
1317
            return true;
1318
        }
1319
        if (other instanceof Money otherMoney) {
1320
            return money.equals(otherMoney.money);
1321
        }
1322
        return false;
1323
    }
1324
1325
    /**
1326
     * Returns a hash code for this monetary value.
1327
     *
1328
     * @return a suitable hash code
1329
     */
1330
    @Override
1331
    public int hashCode() {
1332
        return money.hashCode() + 3;
1333
    }
1334
1335
    //-----------------------------------------------------------------------
1336
    /**
1337
     * Gets the monetary value as a string.
1338
     * <p>
1339
     * The format is the 3 letter ISO currency code, followed by a space,
1340
     * followed by the amount as per {@link BigDecimal#toPlainString()}.
1341
     *
1342
     * @return the string representation of this monetary value, never null
1343
     */
1344
    @Override
1345
    @ToString
1346
    public String toString() {
1347
        return money.toString();
1348
    }
1349
1350
}
1351