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