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}