001/** 002 * Copyright (c) 2012, 2015, Credit Suisse (Anatole Tresch), Werner Keil and others by the @author tag. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 005 * use this file except in compliance with the License. You may obtain a copy of 006 * the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 013 * License for the specific language governing permissions and limitations under 014 * the License. 015 */ 016package org.javamoney.moneta; 017 018import org.javamoney.moneta.ToStringMonetaryAmountFormat.ToStringMonetaryAmountFormatStyle; 019import org.javamoney.moneta.internal.MoneyAmountBuilder; 020import org.javamoney.moneta.spi.DefaultNumberValue; 021import org.javamoney.moneta.spi.MoneyUtils; 022 023import javax.money.*; 024import javax.money.format.MonetaryAmountFormat; 025import java.io.Serializable; 026import java.math.BigDecimal; 027import java.math.MathContext; 028import java.math.RoundingMode; 029import java.util.Objects; 030 031/** 032 * Default immutable implementation of {@link MonetaryAmount} based 033 * on {@link BigDecimal} as numeric representation. 034 * <p> 035 * As required by {@link MonetaryAmount} this class is final, thread-safe, 036 * immutable and serializable. 037 * </p><p> 038 * This class can be configured with an arbitrary {@link MonetaryContext}. The 039 * default {@link MonetaryContext} used models by default the same settings as 040 * {@link MathContext#DECIMAL64} . This default {@link MonetaryContext} can also 041 * be reconfigured by adding a file {@code /javamoney.properties} to the 042 * classpath, with the following content: 043 * </p> 044 * <pre> 045 * # Default MathContext for Money 046 * #------------------------------- 047 * # Custom MonetaryContext, overrides default entries from 048 * # org.javamoney.moneta.Money.monetaryContext 049 * # RoundingMode hereby is optional (default = HALF_EVEN) 050 * org.javamoney.moneta.Money.defaults.precision=256 051 * org.javamoney.moneta.Money.defaults.roundingMode=HALF_EVEN 052 * </pre> 053 * 054 * @author Anatole Tresch 055 * @author Werner Keil 056 * @version 0.7 057 */ 058public final class Money implements MonetaryAmount, Comparable<MonetaryAmount>, Serializable { 059 060 /** 061 * serialVersionUID. 062 */ 063 private static final long serialVersionUID = -7565813772046251748L; 064 065 /** 066 * The default {@link MonetaryContext} applied, if not set explicitly on 067 * creation. 068 */ 069 public static final MonetaryContext DEFAULT_MONETARY_CONTEXT = new DefaultMonetaryContextFactory().getContext(); 070 071 /** 072 * The currency of this amount. 073 */ 074 private final CurrencyUnit currency; 075 076 /** 077 * the {@link MonetaryContext} used by this instance, e.g. on division. 078 */ 079 private final MonetaryContext monetaryContext; 080 081 /** 082 * The numeric part of this amount. 083 */ 084 private final BigDecimal number; 085 086 /** 087 * Creates a new instance os {@link Money}. 088 * 089 * @param currency the currency, not null. 090 * @param number the amount, not null. 091 * @throws ArithmeticException If the number exceeds the capabilities of the default 092 * {@link MonetaryContext}. 093 */ 094 private Money(BigDecimal number, CurrencyUnit currency) { 095 this(number, currency, null); 096 } 097 098 /** 099 * Creates a new instance of {@link Money}. 100 * 101 * @param currency the currency, not {@code null}. 102 * @param number the amount, not {@code null}. 103 * @param monetaryContext the {@link MonetaryContext}, if {@code null}, the default is 104 * used. 105 * @throws ArithmeticException If the number exceeds the capabilities of the 106 * {@link MonetaryContext} used. 107 */ 108 private Money(BigDecimal number, CurrencyUnit currency, MonetaryContext monetaryContext) { 109 Objects.requireNonNull(currency, "Currency is required."); 110 this.currency = currency; 111 if (Objects.nonNull(monetaryContext)) { 112 this.monetaryContext = monetaryContext; 113 } else { 114 this.monetaryContext = DEFAULT_MONETARY_CONTEXT; 115 } 116 Objects.requireNonNull(number, "Number is required."); 117 this.number = MoneyUtils.getBigDecimal(number, monetaryContext); 118 } 119 120 /** 121 * Returns the amount’s currency, modelled as {@link CurrencyUnit}. 122 * Implementations may co-variantly change the return type to a more 123 * specific implementation of {@link CurrencyUnit} if desired. 124 * 125 * @return the currency, never {@code null} 126 * @see javax.money.MonetaryAmount#getCurrency() 127 */ 128 @Override 129 public CurrencyUnit getCurrency() { 130 return currency; 131 } 132 133 /** 134 * Access the {@link MonetaryContext} used by this instance. 135 * 136 * @return the {@link MonetaryContext} used, never null. 137 * @see javax.money.MonetaryAmount#getContext() 138 */ 139 @Override 140 public MonetaryContext getContext() { 141 return monetaryContext; 142 } 143 144 /** 145 * Gets the number representation of the numeric value of this item. 146 * 147 * @return The {@link Number} representation matching best. 148 */ 149 @Override 150 public NumberValue getNumber() { 151 return new DefaultNumberValue(number); 152 } 153 154 /** 155 * Method that returns BigDecimal.ZERO, if {@link #isZero()}, and 156 * {@link #number #stripTrailingZeros()} in all other cases. 157 * 158 * @return the stripped number value. 159 */ 160 public BigDecimal getNumberStripped() { 161 if (isZero()) { 162 return BigDecimal.ZERO; 163 } 164 return this.number.stripTrailingZeros(); 165 } 166 167 /* 168 * @see java.lang.Comparable#compareTo(java.lang.Object) 169 */ 170 @Override 171 public int compareTo(MonetaryAmount o) { 172 Objects.requireNonNull(o); 173 int compare = getCurrency().getCurrencyCode().compareTo(o.getCurrency().getCurrencyCode()); 174 if (compare == 0) { 175 compare = this.number.compareTo(Money.from(o).number); 176 } 177 return compare; 178 } 179 180 // Arithmetic Operations 181 182 /* 183 * (non-Javadoc) 184 * 185 * @see javax.money.MonetaryAmount#abs() 186 */ 187 @Override 188 public Money abs() { 189 if (this.isPositiveOrZero()) { 190 return this; 191 } 192 return negate(); 193 } 194 195 /* 196 * (non-Javadoc) 197 * 198 * @see javax.money.MonetaryAmount#divide(javax.money.MonetaryAmount) 199 */ 200 @Override 201 public Money divide(long divisor) { 202 if (divisor == 1L) { 203 return this; 204 } 205 return divide(BigDecimal.valueOf(divisor)); 206 } 207 208 /* 209 * (non-Javadoc) 210 * 211 * @see javax.money.MonetaryAmount#divide(javax.money.MonetaryAmount) 212 */ 213 @Override 214 public Money divide(double divisor) { 215 if (NumberVerifier.isInfinityAndNotNaN(divisor)) { 216 return Money.of(0, getCurrency()); 217 } 218 if (divisor == 1.0) { 219 return this; 220 } 221 return divide(new BigDecimal(String.valueOf(divisor))); 222 } 223 224 /* 225 * (non-Javadoc) 226 * 227 * @see 228 * javax.money.MonetaryAmount#divideAndRemainder(javax.money.MonetaryAmount) 229 */ 230 @Override 231 public Money[] divideAndRemainder(long divisor) { 232 return divideAndRemainder(BigDecimal.valueOf(divisor)); 233 } 234 235 /* 236 * (non-Javadoc) 237 * 238 * @see 239 * javax.money.MonetaryAmount#divideAndRemainder(javax.money.MonetaryAmount) 240 */ 241 @Override 242 public Money[] divideAndRemainder(double divisor) { 243 if (NumberVerifier.isInfinityAndNotNaN(divisor)) { 244 Money zero = Money.of(0, getCurrency()); 245 return new Money[]{zero, zero}; 246 } 247 return divideAndRemainder(new BigDecimal(String.valueOf(divisor))); 248 } 249 250 /* 251 * (non-Javadoc) 252 * 253 * @see javax.money.MonetaryAmount#multiply(Number) 254 */ 255 @Override 256 public Money multiply(long multiplicand) { 257 if (multiplicand == 1L) { 258 return this; 259 } 260 return multiply(BigDecimal.valueOf(multiplicand)); 261 } 262 263 /* 264 * (non-Javadoc) 265 * 266 * @see javax.money.MonetaryAmount#multiply(Number) 267 */ 268 @Override 269 public Money multiply(double multiplicand) { 270 NumberVerifier.checkNoInfinityOrNaN(multiplicand); 271 if (multiplicand == 1.0d) { 272 return this; 273 } 274 return multiply(new BigDecimal(String.valueOf(multiplicand))); 275 } 276 277 /* 278 * (non-Javadoc) 279 * 280 * @see javax.money.MonetaryAmount#remainder(Number) 281 */ 282 @Override 283 public Money remainder(long divisor) { 284 return remainder(BigDecimal.valueOf(divisor)); 285 } 286 287 /* 288 * (non-Javadoc) 289 * 290 * @see javax.money.MonetaryAmount#remainder(Number) 291 */ 292 @Override 293 public Money remainder(double divisor) { 294 if (NumberVerifier.isInfinityAndNotNaN(divisor)) { 295 return Money.of(0, getCurrency()); 296 } 297 return remainder(new BigDecimal(String.valueOf(divisor))); 298 } 299 300 /* 301 * (non-Javadoc) 302 * 303 * @see javax.money.MonetaryAmount#isZero() 304 */ 305 @Override 306 public boolean isZero() { 307 return signum() == 0; 308 } 309 310 /* 311 * (non-Javadoc) 312 * 313 * @see javax.money.MonetaryAmount#isPositive() 314 */ 315 @Override 316 public boolean isPositive() { 317 return signum() == 1; 318 } 319 320 /* 321 * (non-Javadoc) 322 * 323 * @see javax.money.MonetaryAmount#isPositiveOrZero() 324 */ 325 @Override 326 public boolean isPositiveOrZero() { 327 return signum() >= 0; 328 } 329 330 /* 331 * (non-Javadoc) 332 * 333 * @see javax.money.MonetaryAmount#isNegative() 334 */ 335 @Override 336 public boolean isNegative() { 337 return signum() == -1; 338 } 339 340 /* 341 * (non-Javadoc) 342 * 343 * @see javax.money.MonetaryAmount#isNegativeOrZero() 344 */ 345 @Override 346 public boolean isNegativeOrZero() { 347 return signum() <= 0; 348 } 349 350 351 /* 352 * }(non-Javadoc) 353 * 354 * @see javax.money.MonetaryAmount#query(javax.money.MonetaryQuery) 355 */ 356 @Override 357 public <R> R query(MonetaryQuery<R> query) { 358 Objects.requireNonNull(query); 359 try { 360 return query.queryFrom(this); 361 } catch (MonetaryException e) { 362 throw e; 363 } catch (Exception e) { 364 throw new MonetaryException("Query failed: " + query, e); 365 } 366 } 367 368 /* 369 * (non-Javadoc) 370 * 371 * @see javax.money.MonetaryAmount#with(javax.money.MonetaryOperator) 372 */ 373 @Override 374 public Money with(MonetaryOperator operator) { 375 Objects.requireNonNull(operator); 376 try { 377 return Money.class.cast(operator.apply(this)); 378 } catch (MonetaryException e) { 379 throw e; 380 } catch (Exception e) { 381 throw new MonetaryException("Operator failed: " + operator, e); 382 } 383 } 384 385 /* 386 * (non-Javadoc) 387 * 388 * @see javax.money.MonetaryAmount#add(javax.money.MonetaryAmount) 389 */ 390 @Override 391 public Money add(MonetaryAmount amount) { 392 MoneyUtils.checkAmountParameter(amount, this.currency); 393 if (amount.isZero()) { 394 return this; 395 } 396 return new Money(this.number.add(amount.getNumber().numberValue(BigDecimal.class)), getCurrency()); 397 } 398 399 /* 400 * (non-Javadoc) 401 * 402 * @see javax.money.MonetaryAmount#divide(java.lang.Number) 403 */ 404 @Override 405 public Money divide(Number divisor) { 406 if (NumberVerifier.isInfinityAndNotNaN(divisor)) { 407 return Money.of(0, getCurrency()); 408 } 409 BigDecimal divisorBD = MoneyUtils.getBigDecimal(divisor); 410 if (divisorBD.equals(BigDecimal.ONE)) { 411 return this; 412 } 413 BigDecimal dec = 414 this.number.divide(divisorBD, MoneyUtils.getMathContext(getContext(), RoundingMode.HALF_EVEN)); 415 return new Money(dec, getCurrency()); 416 } 417 418 @Override 419 public Money[] divideAndRemainder(Number divisor) { 420 if (NumberVerifier.isInfinityAndNotNaN(divisor)) { 421 Money zero = Money.of(0, getCurrency()); 422 return new Money[]{zero, zero}; 423 } 424 BigDecimal divisorBD = MoneyUtils.getBigDecimal(divisor); 425 if (divisorBD.equals(BigDecimal.ONE)) { 426 return new Money[]{this, new Money(BigDecimal.ZERO, getCurrency())}; 427 } 428 BigDecimal[] dec = this.number.divideAndRemainder(divisorBD); 429 return new Money[]{new Money(dec[0], getCurrency()), new Money(dec[1], getCurrency())}; 430 } 431 432 /* 433 * (non-Javadoc) 434 * 435 * @see 436 * org.javamoney.moneta.AbstractMoney#divideToIntegralValue(java.lang.Number 437 * ) 438 */ 439 @Override 440 public Money divideToIntegralValue(long divisor) { 441 return divideToIntegralValue(MoneyUtils.getBigDecimal(divisor)); 442 } 443 444 @Override 445 public Money divideToIntegralValue(double divisor) { 446 if (NumberVerifier.isInfinityAndNotNaN(divisor)) { 447 return Money.of(0, getCurrency()); 448 } 449 return divideToIntegralValue(MoneyUtils.getBigDecimal(divisor)); 450 } 451 452 @Override 453 public Money divideToIntegralValue(Number divisor) { 454 if (NumberVerifier.isInfinityAndNotNaN(divisor)) { 455 return Money.of(0, getCurrency()); 456 } 457 BigDecimal divisorBD = MoneyUtils.getBigDecimal(divisor); 458 BigDecimal dec = this.number.divideToIntegralValue(divisorBD); 459 return new Money(dec, getCurrency()); 460 } 461 462 /* 463 * (non-Javadoc) 464 * 465 * @see org.javamoney.moneta.AbstractMoney#multiply(java.lang.Number) 466 */ 467 @Override 468 public Money multiply(Number multiplicand) { 469 NumberVerifier.checkNoInfinityOrNaN(multiplicand); 470 BigDecimal multiplicandBD = MoneyUtils.getBigDecimal(multiplicand); 471 if (multiplicandBD.equals(BigDecimal.ONE)) { 472 return this; 473 } 474 BigDecimal dec = this.number.multiply(multiplicandBD); 475 return new Money(dec, getCurrency()); 476 } 477 478 /* 479 * (non-Javadoc) 480 * 481 * @see javax.money.MonetaryAmount#negate() 482 */ 483 @Override 484 public Money negate() { 485 return new Money(this.number.negate(), getCurrency()); 486 } 487 488 /* 489 * (non-Javadoc) 490 * 491 * @see javax.money.MonetaryAmount#plus() 492 */ 493 @Override 494 public Money plus() { 495 return this; 496 } 497 498 /* 499 * (non-Javadoc) 500 * 501 * @see javax.money.MonetaryAmount#subtract(javax.money.MonetaryAmount) 502 */ 503 @Override 504 public Money subtract(MonetaryAmount amount) { 505 MoneyUtils.checkAmountParameter(amount, this.currency); 506 if (amount.isZero()) { 507 return this; 508 } 509 return new Money(this.number.subtract(amount.getNumber().numberValue(BigDecimal.class)), getCurrency()); 510 } 511 512 /* 513 * (non-Javadoc) 514 * 515 * @see javax.money.MonetaryAmount#stripTrailingZeros() 516 */ 517 @Override 518 public Money stripTrailingZeros() { 519 if (isZero()) { 520 return new Money(BigDecimal.ZERO, getCurrency()); 521 } 522 return new Money(this.number.stripTrailingZeros(), getCurrency()); 523 } 524 525 /* 526 * (non-Javadoc) 527 * 528 * @see org.javamoney.moneta.AbstractMoney#remainder(java.math.BigDecimal) 529 */ 530 @Override 531 public Money remainder(Number divisor) { 532 if (NumberVerifier.isInfinityAndNotNaN(divisor)) { 533 return new Money(BigDecimal.ZERO, getCurrency()); 534 } 535 BigDecimal bd = MoneyUtils.getBigDecimal(divisor); 536 return new Money(this.number.remainder(bd), getCurrency()); 537 } 538 539 /* 540 * (non-Javadoc) 541 * 542 * @see javax.money.MonetaryAmount#scaleByPowerOfTen(int) 543 */ 544 @Override 545 public Money scaleByPowerOfTen(int power) { 546 return new Money(this.number.scaleByPowerOfTen(power), getCurrency()); 547 } 548 549 /* 550 * (non-Javadoc) 551 * 552 * @see javax.money.MonetaryAmount#signum() 553 */ 554 @Override 555 public int signum() { 556 return this.number.signum(); 557 } 558 559 /* 560 * (non-Javadoc) 561 * 562 * @see javax.money.MonetaryAmount#isLessThan(javax.money.MonetaryAmount) 563 */ 564 @Override 565 public boolean isLessThan(MonetaryAmount amount) { 566 MoneyUtils.checkAmountParameter(amount, this.currency); 567 return number.stripTrailingZeros() 568 .compareTo(amount.getNumber().numberValue(BigDecimal.class).stripTrailingZeros()) < 0; 569 } 570 571 /* 572 * (non-Javadoc) 573 * 574 * @see 575 * javax.money.MonetaryAmount#isLessThanOrEqualTo(javax.money.MonetaryAmount 576 * ) 577 */ 578 @Override 579 public boolean isLessThanOrEqualTo(MonetaryAmount amount) { 580 MoneyUtils.checkAmountParameter(amount, this.currency); 581 return number.stripTrailingZeros() 582 .compareTo(amount.getNumber().numberValue(BigDecimal.class).stripTrailingZeros()) <= 0; 583 } 584 585 /* 586 * (non-Javadoc) 587 * 588 * @see javax.money.MonetaryAmount#isGreaterThan(javax.money.MonetaryAmount) 589 */ 590 @Override 591 public boolean isGreaterThan(MonetaryAmount amount) { 592 MoneyUtils.checkAmountParameter(amount, this.currency); 593 return number.stripTrailingZeros() 594 .compareTo(amount.getNumber().numberValue(BigDecimal.class).stripTrailingZeros()) > 0; 595 } 596 597 /* 598 * (non-Javadoc) 599 * 600 * @see 601 * javax.money.MonetaryAmount#isGreaterThanOrEqualTo(javax.money.MonetaryAmount 602 * ) #see 603 */ 604 @Override 605 public boolean isGreaterThanOrEqualTo(MonetaryAmount amount) { 606 MoneyUtils.checkAmountParameter(amount, this.currency); 607 return number.stripTrailingZeros() 608 .compareTo(amount.getNumber().numberValue(BigDecimal.class).stripTrailingZeros()) >= 0; 609 } 610 611 /* 612 * (non-Javadoc) 613 * 614 * @see javax.money.MonetaryAmount#isEqualTo(javax.money.MonetaryAmount) 615 */ 616 @Override 617 public boolean isEqualTo(MonetaryAmount amount) { 618 MoneyUtils.checkAmountParameter(amount, this.currency); 619 return number.stripTrailingZeros() 620 .compareTo(amount.getNumber().numberValue(BigDecimal.class).stripTrailingZeros()) == 0; 621 } 622 623 /* 624 * (non-Javadoc) 625 * 626 * @see javax.money.MonetaryAmount#getFactory() 627 */ 628 @Override 629 public MonetaryAmountFactory<Money> getFactory() { 630 return new MoneyAmountBuilder().setAmount(this); 631 } 632 633 /* 634 * (non-Javadoc) 635 * 636 * @see java.lang.Object#equals(java.lang.Object) 637 */ 638 @Override 639 public boolean equals(Object obj) { 640 if (obj == this) { 641 return true; 642 } 643 if (obj instanceof Money) { 644 Money other = (Money) obj; 645 return Objects.equals(getCurrency(), other.getCurrency()) && 646 Objects.equals(getNumberStripped(), other.getNumberStripped()); 647 } 648 return false; 649 } 650 651 /* 652 * (non-Javadoc) 653 * 654 * @see java.lang.Object#toString() 655 */ 656 @Override 657 public String toString() { 658 return getCurrency().getCurrencyCode() + ' ' + number.toString(); 659 } 660 661 /* 662 * (non-Javadoc) 663 * 664 * @see java.lang.Object#hashCode() 665 */ 666 @Override 667 public int hashCode() { 668 return Objects.hash(getCurrency(), getNumberStripped()); 669 } 670 671 /** 672 * Creates a new instance of {@link Money}, using the default 673 * {@link MonetaryContext}. 674 * 675 * @param number numeric value, not {@code null}. 676 * @param currency currency unit, not {@code null}. 677 * @return a {@code Money} combining the numeric value and currency unit. 678 * @throws ArithmeticException If the number exceeds the capabilities of the default 679 * {@link MonetaryContext} used. 680 */ 681 public static Money of(BigDecimal number, CurrencyUnit currency) { 682 return new Money(number, currency); 683 } 684 685 /** 686 * Creates a new instance of {@link Money}, using an explicit 687 * {@link MonetaryContext}. 688 * 689 * @param number numeric value, not {@code null}. 690 * @param currency currency unit, not {@code null}. 691 * @param monetaryContext the {@link MonetaryContext} to be used, if {@code null} the 692 * default {@link MonetaryContext} is used. 693 * @return a {@code Money} instance based on the monetary context with the 694 * given numeric value, currency unit. 695 * @throws ArithmeticException If the number exceeds the capabilities of the 696 * {@link MonetaryContext} used. 697 */ 698 public static Money of(BigDecimal number, CurrencyUnit currency, MonetaryContext monetaryContext) { 699 return new Money(number, currency, monetaryContext); 700 } 701 702 /** 703 * Creates a new instance of {@link Money}, using the default 704 * {@link MonetaryContext}. 705 * 706 * @param currency The target currency, not null. 707 * @param number The numeric part, not null. 708 * @return A new instance of {@link Money}. 709 * @throws ArithmeticException If the number exceeds the capabilities of the default 710 * {@link MonetaryContext} used. 711 */ 712 public static Money of(Number number, CurrencyUnit currency) { 713 return new Money(MoneyUtils.getBigDecimal(number), currency); 714 } 715 716 /** 717 * Creates a new instance of {@link Money}, using an explicit 718 * {@link MonetaryContext}. 719 * 720 * @param currency The target currency, not null. 721 * @param number The numeric part, not null. 722 * @param monetaryContext the {@link MonetaryContext} to be used, if {@code null} the 723 * default {@link MonetaryContext} is used. 724 * @return A new instance of {@link Money}. 725 * @throws ArithmeticException If the number exceeds the capabilities of the 726 * {@link MonetaryContext} used. 727 */ 728 public static Money of(Number number, CurrencyUnit currency, MonetaryContext monetaryContext) { 729 return new Money(MoneyUtils.getBigDecimal(number), currency, monetaryContext); 730 } 731 732 /** 733 * Static factory method for creating a new instance of {@link Money}. 734 * 735 * @param currencyCode The target currency as ISO currency code. 736 * @param number The numeric part, not null. 737 * @return A new instance of {@link Money}. 738 */ 739 public static Money of(Number number, String currencyCode) { 740 return new Money(MoneyUtils.getBigDecimal(number), Monetary.getCurrency(currencyCode)); 741 } 742 743 /** 744 * Static factory method for creating a new instance of {@link Money}. 745 * 746 * @param currencyCode The target currency as ISO currency code. 747 * @param number The numeric part, not null. 748 * @return A new instance of {@link Money}. 749 */ 750 public static Money of(BigDecimal number, String currencyCode) { 751 return new Money(number, Monetary.getCurrency(currencyCode)); 752 } 753 754 /** 755 * Static factory method for creating a new instance of {@link Money}. 756 * 757 * @param currencyCode The target currency as ISO currency code. 758 * @param number The numeric part, not null. 759 * @param monetaryContext the {@link MonetaryContext} to be used, if {@code null} the 760 * default {@link MonetaryContext} is used. 761 * @return A new instance of {@link Money}. 762 */ 763 public static Money of(Number number, String currencyCode, MonetaryContext monetaryContext) { 764 return new Money(MoneyUtils.getBigDecimal(number), Monetary.getCurrency(currencyCode), 765 monetaryContext); 766 } 767 768 /** 769 * Static factory method for creating a new instance of {@link Money}. 770 * 771 * @param currencyCode The target currency as ISO currency code. 772 * @param number The numeric part, not null. 773 * @param monetaryContext the {@link MonetaryContext} to be used, if {@code null} the 774 * default {@link MonetaryContext} is used. 775 * @return A new instance of {@link Money}. 776 */ 777 public static Money of(BigDecimal number, String currencyCode, MonetaryContext monetaryContext) { 778 return new Money(number, Monetary.getCurrency(currencyCode), monetaryContext); 779 } 780 781 /** 782 * Obtains an instance of {@link Money} representing zero. 783 * @param currency 784 * @return an instance of {@link Money} representing zero. 785 * @since 1.0.1 786 */ 787 public static Money zero(CurrencyUnit currency) { 788 return new Money(BigDecimal.ZERO, currency); 789 } 790 791 /** 792 * Obtains an instance of {@code Money} from an amount in minor units. 793 * For example, {@code ofMinor(USD, 1234)} creates the instance {@code USD 12.34}. 794 * @param currency the currency 795 * @param amountMinor the amount of money in the minor division of the currency 796 * @return the Money from minor units 797 * @throws NullPointerException when the currency is null 798 * @throws IllegalArgumentException when {@link CurrencyUnit#getDefaultFractionDigits()} is lesser than zero. 799 * @see {@link CurrencyUnit#getDefaultFractionDigits()} 800 * @since 1.0.1 801 */ 802 public static Money ofMinor(CurrencyUnit currency, long amountMinor) { 803 return ofMinor(currency, amountMinor, currency.getDefaultFractionDigits()); 804 } 805 806 /** 807 * Obtains an instance of {@code Money} from an amount in minor units. 808 * For example, {@code ofMinor(USD, 1234, 2)} creates the instance {@code USD 12.34}. 809 * @param currency the currency, not null 810 * @param amountMinor the amount of money in the minor division of the currency 811 * @param fractionDigits number of digits 812 * @return the monetary amount from minor units 813 * @see {@link CurrencyUnit#getDefaultFractionDigits()} 814 * @see {@link Money#ofMinor(CurrencyUnit, long, int)} 815 * @throws NullPointerException when the currency is null 816 * @throws IllegalArgumentException when the fractionDigits is negative 817 * @since 1.0.1 818 */ 819 public static Money ofMinor(CurrencyUnit currency, long amountMinor, int fractionDigits) { 820 if(fractionDigits < 0) { 821 throw new IllegalArgumentException("The fractionDigits cannot be negative"); 822 } 823 return of(BigDecimal.valueOf(amountMinor, fractionDigits), currency); 824 } 825 826 /** 827 * Converts (if necessary) the given {@link MonetaryAmount} to a 828 * {@link Money} instance. The {@link MonetaryContext} will be adapted as 829 * necessary, if the precision of the given amount exceeds the capabilities 830 * of the default {@link MonetaryContext}. 831 * 832 * @param amt the amount to be converted 833 * @return an according Money instance. 834 */ 835 public static Money from(MonetaryAmount amt) { 836 if (amt.getClass() == Money.class) { 837 return (Money) amt; 838 } 839 return Money.of(amt.getNumber().numberValue(BigDecimal.class), amt.getCurrency(), amt.getContext()); 840 } 841 842 /** 843 * Obtains an instance of Money from a text string such as 'EUR 25.25'. 844 * 845 * @param text the text to parse not null 846 * @return Money instance 847 * @throws NullPointerException 848 * @throws NumberFormatException 849 * @throws UnknownCurrencyException 850 */ 851 public static Money parse(CharSequence text) { 852 return parse(text, DEFAULT_FORMATTER); 853 } 854 855 /** 856 * Obtains an instance of Money from a text using specific formatter. 857 * 858 * @param text the text to parse not null 859 * @param formatter the formatter to use not null 860 * @return Money instance 861 */ 862 public static Money parse(CharSequence text, MonetaryAmountFormat formatter) { 863 return from(formatter.parse(text)); 864 } 865 866 private static final ToStringMonetaryAmountFormat DEFAULT_FORMATTER = ToStringMonetaryAmountFormat 867 .of(ToStringMonetaryAmountFormatStyle.MONEY); 868 869 /** 870 * Just to don't break the compatibility. 871 * Don't use it 872 * @param number 873 */ 874 @Deprecated 875 public static boolean isInfinityAndNotNaN(Number number) { 876 if (Double.class == number.getClass() || Float.class == number.getClass()) { 877 double dValue = number.doubleValue(); 878 if (Double.isNaN(dValue)) { 879 throw new ArithmeticException("Not a valid input: NaN."); 880 } else if (Double.isInfinite(dValue)) { 881 return true; 882 } 883 } 884 return false; 885 } 886 /** 887 * Just to don't break the compatibility. 888 * Don't use it 889 * @param number 890 */ 891 @Deprecated 892 public static void checkNoInfinityOrNaN(Number number) { 893 if (Double.class == number.getClass() || Float.class == number.getClass()) { 894 double dValue = number.doubleValue(); 895 if (Double.isNaN(dValue)) { 896 throw new ArithmeticException("Not a valid input: NaN."); 897 } else if (Double.isInfinite(dValue)) { 898 throw new ArithmeticException("Not a valid input: INFINITY: " + dValue); 899 } 900 } 901 } 902}