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