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