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