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.Monetary;
026import javax.money.MonetaryAmount;
027import javax.money.MonetaryAmountFactory;
028import javax.money.MonetaryContext;
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.spi.MoneyAmountFactory;
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 *
045 * As required by {@link MonetaryAmount} this class is final, thread-safe,
046 * immutable and serializable.
047 *
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 *
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 final 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 (monetaryContext!=null) {
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} representation 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 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 MonetaryAmount#divide(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 MonetaryAmount#divide(MonetaryAmount)
222     */
223    @Override
224    public Money divide(double divisor) {
225        if (NumberVerifier.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     * MonetaryAmount#divideAndRemainder(MonetaryAmount)
239     */
240    @Override
241    public Money[] divideAndRemainder(long divisor) {
242        return divideAndRemainder(BigDecimal.valueOf(divisor));
243    }
244
245    /*
246     * (non-Javadoc)
247     *
248     * @see
249     * MonetaryAmount#divideAndRemainder(MonetaryAmount)
250     */
251    @Override
252    public Money[] divideAndRemainder(double divisor) {
253        if (NumberVerifier.isInfinityAndNotNaN(divisor)) {
254            Money zero = Money.of(0, getCurrency());
255            return new Money[]{zero, zero};
256        }
257        return divideAndRemainder(new BigDecimal(String.valueOf(divisor)));
258    }
259
260    /*
261     * (non-Javadoc)
262     *
263     * @see MonetaryAmount#multiply(Number)
264     */
265    @Override
266    public Money multiply(long multiplicand) {
267        if (multiplicand == 1L) {
268            return this;
269        }
270        return multiply(BigDecimal.valueOf(multiplicand));
271    }
272
273    /*
274     * (non-Javadoc)
275     *
276     * @see MonetaryAmount#multiply(Number)
277     */
278    @Override
279    public Money multiply(double multiplicand) {
280        NumberVerifier.checkNoInfinityOrNaN(multiplicand);
281        if (multiplicand == 1.0d) {
282            return this;
283        }
284        return multiply(new BigDecimal(String.valueOf(multiplicand)));
285    }
286
287    /*
288     * (non-Javadoc)
289     *
290     * @see MonetaryAmount#remainder(Number)
291     */
292    @Override
293    public Money remainder(long divisor) {
294        return remainder(BigDecimal.valueOf(divisor));
295    }
296
297    /*
298     * (non-Javadoc)
299     *
300     * @see MonetaryAmount#remainder(Number)
301     */
302    @Override
303    public Money remainder(double divisor) {
304        if (NumberVerifier.isInfinityAndNotNaN(divisor)) {
305            return Money.of(0, getCurrency());
306        }
307        return remainder(new BigDecimal(String.valueOf(divisor)));
308    }
309
310    /*
311     * (non-Javadoc)
312     *
313     * @see javax.money.MonetaryAmount#isZero()
314     */
315    @Override
316    public boolean isZero() {
317        return signum() == 0;
318    }
319
320    /*
321     * (non-Javadoc)
322     *
323     * @see javax.money.MonetaryAmount#isPositive()
324     */
325    @Override
326    public boolean isPositive() {
327        return signum() == 1;
328    }
329
330    /*
331     * (non-Javadoc)
332     *
333     * @see javax.money.MonetaryAmount#isPositiveOrZero()
334     */
335    @Override
336    public boolean isPositiveOrZero() {
337        return signum() >= 0;
338    }
339
340    /*
341     * (non-Javadoc)
342     *
343     * @see javax.money.MonetaryAmount#isNegative()
344     */
345    @Override
346    public boolean isNegative() {
347        return signum() == -1;
348    }
349
350    /*
351     * (non-Javadoc)
352     *
353     * @see javax.money.MonetaryAmount#isNegativeOrZero()
354     */
355    @Override
356    public boolean isNegativeOrZero() {
357        return signum() <= 0;
358    }
359
360
361    /*
362     * }(non-Javadoc)
363     *
364     * @see javax.money.MonetaryAmount#query(javax.money.MonetaryQuery)
365     */
366    @Override
367    public <R> R query(MonetaryQuery<R> query) {
368        Objects.requireNonNull(query);
369        try {
370            return query.queryFrom(this);
371        } catch (MonetaryException e) {
372            throw e;
373        } catch (Exception e) {
374            throw new MonetaryException("Query failed: " + query, e);
375        }
376    }
377
378    /*
379     * (non-Javadoc)
380     *
381     * @see javax.money.MonetaryAmount#with(javax.money.MonetaryOperator)
382     */
383    @Override
384    public Money with(MonetaryOperator operator) {
385        Objects.requireNonNull(operator);
386        try {
387            return Money.class.cast(operator.apply(this));
388        } catch (MonetaryException e) {
389            throw e;
390        } catch (Exception e) {
391            throw new MonetaryException("Operator failed: " + operator, e);
392        }
393    }
394
395    /*
396     * (non-Javadoc)
397     *
398     * @see javax.money.MonetaryAmount#add(javax.money.MonetaryAmount)
399     */
400    @Override
401    public Money add(MonetaryAmount amount) {
402        MoneyUtils.checkAmountParameter(amount, this.currency);
403        if (amount.isZero()) {
404            return this;
405        }
406        return new Money(this.number.add(amount.getNumber().numberValue(BigDecimal.class)), getCurrency());
407    }
408
409    /*
410     * (non-Javadoc)
411     *
412     * @see javax.money.MonetaryAmount#divide(java.lang.Number)
413     */
414    @Override
415    public Money divide(Number divisor) {
416        if (NumberVerifier.isInfinityAndNotNaN(divisor)) {
417            return Money.of(0, getCurrency());
418        }
419        BigDecimal divisorBD = MoneyUtils.getBigDecimal(divisor);
420        if (divisorBD.equals(BigDecimal.ONE)) {
421            return this;
422        }
423        BigDecimal dec =
424                this.number.divide(divisorBD, MoneyUtils.getMathContext(getContext(), RoundingMode.HALF_EVEN));
425        return new Money(dec, getCurrency());
426    }
427
428    @Override
429    public Money[] divideAndRemainder(Number divisor) {
430        if (NumberVerifier.isInfinityAndNotNaN(divisor)) {
431            Money zero = Money.of(0, getCurrency());
432            return new Money[]{zero, zero};
433        }
434        BigDecimal divisorBD = MoneyUtils.getBigDecimal(divisor);
435        if (divisorBD.equals(BigDecimal.ONE)) {
436            return new Money[]{this, new Money(BigDecimal.ZERO, getCurrency())};
437        }
438        BigDecimal[] dec = this.number.divideAndRemainder(divisorBD);
439        return new Money[]{new Money(dec[0], getCurrency()), new Money(dec[1], getCurrency())};
440    }
441
442    /*
443     * (non-Javadoc)
444     *
445     * @see
446     * org.javamoney.moneta.AbstractMoney#divideToIntegralValue(java.lang.Number
447     * )
448     */
449    @Override
450    public Money divideToIntegralValue(long divisor) {
451        return divideToIntegralValue(MoneyUtils.getBigDecimal(divisor));
452    }
453
454    @Override
455    public Money divideToIntegralValue(double divisor) {
456        if (NumberVerifier.isInfinityAndNotNaN(divisor)) {
457            return Money.of(0, getCurrency());
458        }
459        return divideToIntegralValue(MoneyUtils.getBigDecimal(divisor));
460    }
461
462    @Override
463    public Money divideToIntegralValue(Number divisor) {
464        if (NumberVerifier.isInfinityAndNotNaN(divisor)) {
465            return Money.of(0, getCurrency());
466        }
467        BigDecimal divisorBD = MoneyUtils.getBigDecimal(divisor);
468        BigDecimal dec = this.number.divideToIntegralValue(divisorBD);
469        return new Money(dec, getCurrency());
470    }
471
472    /*
473     * (non-Javadoc)
474     *
475     * @see org.javamoney.moneta.AbstractMoney#multiply(java.lang.Number)
476     */
477    @Override
478    public Money multiply(Number multiplicand) {
479          NumberVerifier.checkNoInfinityOrNaN(multiplicand);
480        BigDecimal multiplicandBD = MoneyUtils.getBigDecimal(multiplicand);
481        if (multiplicandBD.equals(BigDecimal.ONE)) {
482            return this;
483        }
484        BigDecimal dec = this.number.multiply(multiplicandBD);
485        return new Money(dec, getCurrency());
486    }
487
488    /*
489     * (non-Javadoc)
490     *
491     * @see javax.money.MonetaryAmount#negate()
492     */
493    @Override
494    public Money negate() {
495        return new Money(this.number.negate(), getCurrency());
496    }
497
498    /*
499     * (non-Javadoc)
500     *
501     * @see javax.money.MonetaryAmount#plus()
502     */
503    @Override
504    public Money plus() {
505        return this;
506    }
507
508    /*
509     * (non-Javadoc)
510     *
511     * @see javax.money.MonetaryAmount#subtract(javax.money.MonetaryAmount)
512     */
513    @Override
514    public Money subtract(MonetaryAmount subtrahend) {
515        MoneyUtils.checkAmountParameter(subtrahend, this.currency);
516        if (subtrahend.isZero()) {
517            return this;
518        }
519        return new Money(this.number.subtract(subtrahend.getNumber().numberValue(BigDecimal.class)), getCurrency());
520    }
521
522    /*
523     * (non-Javadoc)
524     *
525     * @see javax.money.MonetaryAmount#stripTrailingZeros()
526     */
527    @Override
528    public Money stripTrailingZeros() {
529        if (isZero()) {
530            return new Money(BigDecimal.ZERO, getCurrency());
531        }
532        return new Money(this.number.stripTrailingZeros(), getCurrency());
533    }
534
535    /*
536     * (non-Javadoc)
537     *
538     * @see org.javamoney.moneta.AbstractMoney#remainder(java.math.BigDecimal)
539     */
540    @Override
541    public Money remainder(Number divisor) {
542        if (NumberVerifier.isInfinityAndNotNaN(divisor)) {
543            return new Money(BigDecimal.ZERO, getCurrency());
544        }
545        BigDecimal bd = MoneyUtils.getBigDecimal(divisor);
546        return new Money(this.number.remainder(bd), getCurrency());
547    }
548
549    /*
550     * (non-Javadoc)
551     *
552     * @see javax.money.MonetaryAmount#scaleByPowerOfTen(int)
553     */
554    @Override
555    public Money scaleByPowerOfTen(int power) {
556        return new Money(this.number.scaleByPowerOfTen(power), getCurrency());
557    }
558
559    /*
560     * (non-Javadoc)
561     *
562     * @see javax.money.MonetaryAmount#signum()
563     */
564    @Override
565    public int signum() {
566        return this.number.signum();
567    }
568
569    /*
570     * (non-Javadoc)
571     *
572     * @see javax.money.MonetaryAmount#isLessThan(javax.money.MonetaryAmount)
573     */
574    @Override
575    public boolean isLessThan(MonetaryAmount amount) {
576        MoneyUtils.checkAmountParameter(amount, this.currency);
577        return number.stripTrailingZeros()
578                .compareTo(amount.getNumber().numberValue(BigDecimal.class).stripTrailingZeros()) < 0;
579    }
580
581    /*
582     * (non-Javadoc)
583     *
584     * @see
585     * javax.money.MonetaryAmount#isLessThanOrEqualTo(javax.money.MonetaryAmount
586     * )
587     */
588    @Override
589    public boolean isLessThanOrEqualTo(MonetaryAmount amount) {
590        MoneyUtils.checkAmountParameter(amount, this.currency);
591        return number.stripTrailingZeros()
592                .compareTo(amount.getNumber().numberValue(BigDecimal.class).stripTrailingZeros()) <= 0;
593    }
594
595    /*
596     * (non-Javadoc)
597     *
598     * @see javax.money.MonetaryAmount#isGreaterThan(javax.money.MonetaryAmount)
599     */
600    @Override
601    public boolean isGreaterThan(MonetaryAmount amount) {
602        MoneyUtils.checkAmountParameter(amount, this.currency);
603        return number.stripTrailingZeros()
604                .compareTo(amount.getNumber().numberValue(BigDecimal.class).stripTrailingZeros()) > 0;
605    }
606
607    /*
608     * (non-Javadoc)
609     *
610     * @see
611     * javax.money.MonetaryAmount#isGreaterThanOrEqualTo(javax.money.MonetaryAmount
612     * ) #see
613     */
614    @Override
615    public boolean isGreaterThanOrEqualTo(MonetaryAmount amount) {
616        MoneyUtils.checkAmountParameter(amount, this.currency);
617        return number.stripTrailingZeros()
618                .compareTo(amount.getNumber().numberValue(BigDecimal.class).stripTrailingZeros()) >= 0;
619    }
620
621    /*
622     * (non-Javadoc)
623     *
624     * @see javax.money.MonetaryAmount#isEqualTo(javax.money.MonetaryAmount)
625     */
626    @Override
627    public boolean isEqualTo(MonetaryAmount amount) {
628        MoneyUtils.checkAmountParameter(amount, this.currency);
629        return number.stripTrailingZeros()
630                .compareTo(amount.getNumber().numberValue(BigDecimal.class).stripTrailingZeros()) == 0;
631    }
632
633    /*
634     * (non-Javadoc)
635     *
636     * @see javax.money.MonetaryAmount#getFactory()
637     */
638    @Override
639    public MonetaryAmountFactory<Money> getFactory() {
640        return new MoneyAmountFactory().setAmount(this);
641    }
642
643    /*
644     * (non-Javadoc)
645     *
646     * @see java.lang.Object#equals(java.lang.Object)
647     */
648    @Override
649    public boolean equals(Object obj) {
650        if (obj == this) {
651            return true;
652        }
653        if (obj instanceof Money) {
654            Money other = (Money) obj;
655            return Objects.equals(getCurrency(), other.getCurrency()) &&
656                    Objects.equals(getNumberStripped(), other.getNumberStripped());
657        }
658        return false;
659    }
660
661    /*
662     * (non-Javadoc)
663     *
664     * @see java.lang.Object#toString()
665     */
666    @Override
667    public String toString() {
668        return getCurrency().getCurrencyCode() + ' ' + number.toPlainString();
669    }
670
671    /*
672     * (non-Javadoc)
673     *
674     * @see java.lang.Object#hashCode()
675     */
676    @Override
677    public int hashCode() {
678        return Objects.hash(getCurrency(), getNumberStripped());
679    }
680
681    /**
682     * Creates a new instance of {@link Money}, using the default
683     * {@link MonetaryContext}.
684     *
685     * @param number   numeric value, not {@code null}.
686     * @param currency currency unit, not {@code null}.
687     * @return a {@code Money} combining the numeric value and currency unit.
688     * @throws ArithmeticException If the number exceeds the capabilities of the default
689     *                             {@link MonetaryContext} used.
690     */
691    public static Money of(BigDecimal number, CurrencyUnit currency) {
692        return new Money(number, currency);
693    }
694
695    /**
696     * Creates a new instance of {@link Money}, using an explicit
697     * {@link MonetaryContext}.
698     *
699     * @param number          numeric value, not {@code null}.
700     * @param currency        currency unit, not {@code null}.
701     * @param monetaryContext the {@link MonetaryContext} to be used, if {@code null} the
702     *                        default {@link MonetaryContext} is used.
703     * @return a {@code Money} instance based on the monetary context with the
704     * given numeric value, currency unit.
705     * @throws ArithmeticException If the number exceeds the capabilities of the
706     *                             {@link MonetaryContext} used.
707     */
708    public static Money of(BigDecimal number, CurrencyUnit currency, MonetaryContext monetaryContext) {
709        return new Money(number, currency, monetaryContext);
710    }
711
712    /**
713     * Creates a new instance of {@link Money}, using the default
714     * {@link MonetaryContext}.
715     *
716     * @param currency The target currency, not null.
717     * @param number   The numeric part, not null.
718     * @return A new instance of {@link Money}.
719     * @throws ArithmeticException If the number exceeds the capabilities of the default
720     *                             {@link MonetaryContext} used.
721     */
722    public static Money of(Number number, CurrencyUnit currency) {
723        return new Money(MoneyUtils.getBigDecimal(number), currency);
724    }
725
726    /**
727     * Creates a new instance of {@link Money}, using an explicit
728     * {@link MonetaryContext}.
729     *
730     * @param currency        The target currency, not null.
731     * @param number          The numeric part, not null.
732     * @param monetaryContext the {@link MonetaryContext} to be used, if {@code null} the
733     *                        default {@link MonetaryContext} is used.
734     * @return A new instance of {@link Money}.
735     * @throws ArithmeticException If the number exceeds the capabilities of the
736     *                             {@link MonetaryContext} used.
737     */
738    public static Money of(Number number, CurrencyUnit currency, MonetaryContext monetaryContext) {
739        return new Money(MoneyUtils.getBigDecimal(number), currency, monetaryContext);
740    }
741
742    /**
743     * Static factory method for creating a new instance of {@link Money}.
744     *
745     * @param currencyCode The target currency as ISO currency code.
746     * @param number       The numeric part, not null.
747     * @return A new instance of {@link Money}.
748     */
749    public static Money of(Number number, String currencyCode) {
750        return new Money(MoneyUtils.getBigDecimal(number), Monetary.getCurrency(currencyCode));
751    }
752
753    /**
754     * Static factory method for creating a new instance of {@link Money}.
755     *
756     * @param currencyCode The target currency as ISO currency code.
757     * @param number       The numeric part, not null.
758     * @return A new instance of {@link Money}.
759     */
760    public static Money of(BigDecimal number, String currencyCode) {
761        return new Money(number, Monetary.getCurrency(currencyCode));
762    }
763
764    /**
765     * Static factory method for creating a new instance of {@link Money}.
766     *
767     * @param currencyCode    The target currency as ISO currency code.
768     * @param number          The numeric part, not null.
769     * @param monetaryContext the {@link MonetaryContext} to be used, if {@code null} the
770     *                        default {@link MonetaryContext} is used.
771     * @return A new instance of {@link Money}.
772     */
773    public static Money of(Number number, String currencyCode, MonetaryContext monetaryContext) {
774        return new Money(MoneyUtils.getBigDecimal(number), Monetary.getCurrency(currencyCode),
775                monetaryContext);
776    }
777
778    /**
779     * Static factory method for creating a new instance of {@link Money}.
780     *
781     * @param currencyCode    The target currency as ISO currency code.
782     * @param number          The numeric part, not null.
783     * @param monetaryContext the {@link MonetaryContext} to be used, if {@code null} the
784     *                        default {@link MonetaryContext} is used.
785     * @return A new instance of {@link Money}.
786     */
787    public static Money of(BigDecimal number, String currencyCode, MonetaryContext monetaryContext) {
788        return new Money(number, Monetary.getCurrency(currencyCode), monetaryContext);
789    }
790
791    /**
792     * Obtains an instance of {@link Money} representing zero.
793     * @param currency the currency, not null.
794     * @return an instance of {@link Money} representing zero.
795     * @since 1.0.1
796     */
797    public static Money zero(CurrencyUnit currency) {
798        return new Money(BigDecimal.ZERO, currency);
799    }
800
801         /**
802      * Obtains an instance of {@code Money} from an amount in minor units.
803      * For example, {@code ofMinor(USD, 1234)} creates the instance {@code USD 12.34}.
804      * @param currency  the currency
805      * @param amountMinor  the amount of money in the minor division of the currency
806      * @return the Money from minor units
807      * @throws NullPointerException when the currency is null
808      * @throws IllegalArgumentException when {@link CurrencyUnit#getDefaultFractionDigits()} is lesser than zero.
809      * @see CurrencyUnit#getDefaultFractionDigits()
810      * @since 1.0.1
811      */
812     public static Money ofMinor(CurrencyUnit currency, long amountMinor) {
813         return ofMinor(currency, amountMinor, currency.getDefaultFractionDigits());
814     }
815
816     /**
817      * Obtains an instance of {@code Money} from an amount in minor units.
818      * For example, {@code ofMinor(USD, 1234, 2)} creates the instance {@code USD 12.34}.
819      * @param currency  the currency, not null
820      * @param amountMinor  the amount of money in the minor division of the currency
821      * @param factionDigits number of digits
822      * @return the monetary amount from minor units
823      * @see CurrencyUnit#getDefaultFractionDigits()
824      * @see Money#ofMinor(CurrencyUnit, long, int)
825      * @throws NullPointerException when the currency is null
826      * @throws IllegalArgumentException when the factionDigits is negative
827      * @since 1.0.1
828      */
829     public static Money ofMinor(CurrencyUnit currency, long amountMinor, int factionDigits) {
830        if(factionDigits < 0) {
831                throw new IllegalArgumentException("The factionDigits cannot be negative");
832        }
833        return of(BigDecimal.valueOf(amountMinor, factionDigits), currency);
834     }
835
836    /**
837     * Converts (if necessary) the given {@link MonetaryAmount} to a
838     * {@link Money} instance. The {@link MonetaryContext} will be adapted as
839     * necessary, if the precision of the given amount exceeds the capabilities
840     * of the default {@link MonetaryContext}.
841     *
842     * @param amt the amount to be converted
843     * @return an according Money instance.
844     */
845    public static Money from(MonetaryAmount amt) {
846        if (amt.getClass() == Money.class) {
847            return (Money) amt;
848        }
849        return Money.of(amt.getNumber().numberValue(BigDecimal.class), amt.getCurrency(), amt.getContext());
850    }
851
852    /**
853     * Obtains an instance of Money from a text string such as 'EUR 25.25'.
854     *
855     * @param text the text to parse, not null
856     * @return Money instance
857     * @throws NumberFormatException if the amount is not parseable.
858     * @throws UnknownCurrencyException if the currency is not resolvable.
859     */
860    public static Money parse(CharSequence text) {
861        return parse(text, DEFAULT_FORMATTER);
862    }
863
864    /**
865     * Obtains an instance of Money from a text using specific formatter.
866     *
867     * @param text      the text to parse not null
868     * @param formatter the formatter to use not null
869     * @return Money instance
870     */
871    public static Money parse(CharSequence text, MonetaryAmountFormat formatter) {
872        return from(formatter.parse(text));
873    }
874
875    private static final ToStringMonetaryAmountFormat DEFAULT_FORMATTER = ToStringMonetaryAmountFormat
876            .of(ToStringMonetaryAmountFormatStyle.MONEY);
877
878    /**
879     * Just to don't break the compatibility.
880     * Don't use it
881     * @param number the number, not null.
882     * @deprecated Will be removed.
883     */
884    @Deprecated
885    public static boolean isInfinityAndNotNaN(Number number) {
886        if (Double.class == number.getClass() || Float.class == number.getClass()) {
887            double dValue = number.doubleValue();
888            if (!Double.isNaN(dValue) && Double.isInfinite(dValue)) {
889                return true;
890            }
891        }
892        return false;
893    }
894
895
896    /**
897     * Just to don't break the compatibility.
898     * Don't use it
899     * @param number the number, not null.
900     * @deprecated Will be removed.
901     */
902    @Deprecated
903    public static void checkNoInfinityOrNaN(Number number) {
904        if (Double.class == number.getClass() || Float.class == number.getClass()) {
905            double dValue = number.doubleValue();
906            if (Double.isNaN(dValue)) {
907                throw new ArithmeticException("Not a valid input: NaN.");
908            } else if (Double.isInfinite(dValue)) {
909                throw new ArithmeticException("Not a valid input: INFINITY: " + dValue);
910            }
911        }
912    }
913
914}