001package org.javamoney.moneta;
002
003import org.javamoney.moneta.internal.ConfigurableCurrencyUnitProvider;
004
005import javax.money.CurrencyContextBuilder;
006import javax.money.CurrencyUnit;
007import java.util.Locale;
008import java.util.Objects;
009
010/**
011 * Builder for constructing new instances o{@link BuildableCurrencyUnit} using a fluent
012 * API.
013 */
014public final class CurrencyUnitBuilder{
015    /**
016     * The currency code.
017     */
018    String currencyCode;
019    /**
020     * The (optional) numeric code.
021     */
022    int numericCode = -1;
023    /**
024     * The default fraction digits.
025     */
026    int defaultFractionDigits = 2;
027    /**
028     * The currency's context.
029     */
030    javax.money.CurrencyContext currencyContext;
031
032    /**
033     * Private constructor, use #of() methods.
034     */
035    private CurrencyUnitBuilder(){
036    }
037
038    /**
039     * Creats a new CurrencyUnitBuilder.
040     *
041     * @param currencyCode    the (unique) and identifying currency code, not null.
042     * @param currencyContext The currency context to be used.
043     */
044    public static CurrencyUnitBuilder of(String currencyCode, javax.money.CurrencyContext currencyContext){
045        return new CurrencyUnitBuilder(currencyCode, currencyContext);
046    }
047
048    /**
049     * Creats a new CurrencyUnitBuilder, creates a simple CurrencyContext using the given provider name.
050     *
051     * @param currencyCode the (unique) and identifying currency code, not null.
052     * @param providerName the currency provider, not null.
053     */
054    public static CurrencyUnitBuilder of(String currencyCode, String providerName){
055        return new CurrencyUnitBuilder(currencyCode, CurrencyContextBuilder.of(providerName).build());
056    }
057
058    /**
059     * Creats a new Builder.
060     *
061     * @param currencyCode the (unique) and identifying currency code, not null.
062     */
063    private CurrencyUnitBuilder(String currencyCode, javax.money.CurrencyContext currencyContext){
064        Objects.requireNonNull(currencyCode, "currencyCode required");
065        this.currencyCode = currencyCode;
066        Objects.requireNonNull(currencyContext, "currencyContext required");
067        this.currencyContext = currencyContext;
068    }
069
070    /**
071     * Allows to set the currency code, for creating multiple instances, using one Builder.
072     *
073     * @param currencyCode the (unique) and identifying currency code, not null.
074     * @return the Builder, for chaining.
075     * @see javax.money.CurrencyUnit#getCurrencyCode()
076     */
077    public CurrencyUnitBuilder setCurrencyCode(String currencyCode){
078        Objects.requireNonNull(currencyCode, "currencyCode required");
079        this.currencyCode = currencyCode;
080        this.currencyContext = CurrencyContextBuilder.of(getClass().getSimpleName()).build();
081        return this;
082    }
083
084    /**
085     * Set the numeric code (optional).
086     *
087     * @param numericCode The numeric currency code, &gt;= -1. .1 hereby means <i>undefined</i>.
088     * @return the Builder, for chaining.
089     * @see javax.money.CurrencyUnit#getNumericCode()
090     */
091    public CurrencyUnitBuilder setNumericCode(int numericCode){
092        if(numericCode < -1){
093            throw new IllegalArgumentException("numericCode must be >= -1");
094        }
095        this.numericCode = numericCode;
096        return this;
097    }
098
099    /**
100     * Set the default fraction digits.
101     *
102     * @param defaultFractionDigits the default fraction digits, &gt;= 0.
103     * @return the Builder, for chaining.
104     * @see javax.money.CurrencyUnit#getDefaultFractionDigits()
105     */
106    public CurrencyUnitBuilder setDefaultFractionDigits(int defaultFractionDigits){
107        if(defaultFractionDigits < 0){
108            throw new IllegalArgumentException("defaultFractionDigits must be >= 0");
109        }
110        this.defaultFractionDigits = defaultFractionDigits;
111        return this;
112    }
113
114    /**
115     * Returns a new instance of {@link BuildableCurrencyUnit}.
116     *
117     * @return the new CurrencyUnit instance.
118     * @throws javax.money.MonetaryException if creation fails
119     */
120    public CurrencyUnit build(){
121        return build(false);
122    }
123
124    /**
125     * Returns a new instance of {@link BuildableCurrencyUnit} and publishes it so it is
126     * accessible from the {@code MonetaryCurrencies} singleton.
127     *
128     * @param register if {@code true} the instance created is published so it is accessible from
129     *                 the {@code MonetaryCurrencies} singleton.
130     * @return the new CurrencyUnit instance.
131     * @see javax.money.MonetaryCurrencies#getCurrency(String, String...)
132     */
133    public CurrencyUnit build(boolean register){
134        BuildableCurrencyUnit cu = new BuildableCurrencyUnit(this);
135        if(register){
136            ConfigurableCurrencyUnitProvider.registerCurrencyUnit(cu);
137        }
138        return cu;
139    }
140
141    /**
142     * Returns a new instance of {@link BuildableCurrencyUnit} and publishes it so it is
143     * accessible from the {@code MonetaryCurrencies} singleton.
144     *
145     * @param register if {@code true} the instance created is published so it is accessible from
146     *                 the {@code MonetaryCurrencies} singleton.
147     * @param locale   country Locale for making the currency for the given country.
148     * @return the new CurrencyUnit instance.
149     * @see javax.money.MonetaryCurrencies#getCurrency(String, String...)
150     * @see javax.money.MonetaryCurrencies#getCurrency(java.util.Locale, String...)
151     */
152    public CurrencyUnit build(boolean register, Locale locale){
153        BuildableCurrencyUnit cu = new BuildableCurrencyUnit(this);
154        if(register){
155            ConfigurableCurrencyUnitProvider.registerCurrencyUnit(cu);
156            ConfigurableCurrencyUnitProvider.registerCurrencyUnit(cu, locale);
157        }
158        return cu;
159    }
160}