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