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 org.javamoney.moneta.internal.ConfigurableCurrencyUnitProvider;
019
020import javax.money.*;
021import javax.money.CurrencyContext;
022
023import java.util.Locale;
024import java.util.Objects;
025
026/**
027 * Implementation of {@link javax.money.CurrencyUnit} that allows to create new instances using a fluent API.
028 * Instances created also can be added to the {@link org.javamoney.moneta.internal.ConfigurableCurrencyUnitProvider}
029 * singleton, which publishes the instances, so they are visible from the {@link javax.money.MonetaryCurrencies}
030 * singleton.
031 */
032public final class BuildableCurrencyUnit implements CurrencyUnit, Comparable<CurrencyUnit>{
033
034    /**
035     * The unique currency code.
036     */
037    private String currencyCode;
038    /**
039     * The (optional) numeric code.
040     */
041    private int numericCode;
042    /**
043     * The default fraction digits.
044     */
045    private int defaultFractionDigits;
046    /**
047     * THe currency's context.
048     */
049    private javax.money.CurrencyContext currencyContext;
050
051    /**
052     * Constructor, called from the Builder.
053     *
054     * @param builder the builder, never null.
055     */
056    private BuildableCurrencyUnit(Builder builder){
057        Objects.requireNonNull(builder.currencyCode, "currencyCode required");
058        if(builder.numericCode < -1){
059            throw new MonetaryException("numericCode must be >= -1");
060        }
061        if(builder.defaultFractionDigits < 0){
062            throw new MonetaryException("defaultFractionDigits must be >= 0");
063        }
064        if(builder.currencyContext == null){
065            throw new MonetaryException("currencyContext must be != null");
066        }
067        this.defaultFractionDigits = builder.defaultFractionDigits;
068        this.numericCode = builder.numericCode;
069        this.currencyCode = builder.currencyCode;
070        this.currencyContext = builder.currencyContext;
071    }
072
073    @Override
074    public String getCurrencyCode(){
075        return currencyCode;
076    }
077
078    @Override
079    public int getNumericCode(){
080        return numericCode;
081    }
082
083    @Override
084    public int getDefaultFractionDigits(){
085        return defaultFractionDigits;
086    }
087
088    @Override
089    public CurrencyContext getCurrencyContext(){
090        return currencyContext;
091    }
092
093    @Override
094    public int compareTo(CurrencyUnit o){
095        Objects.requireNonNull(o);
096        return this.currencyCode.compareTo(o.getCurrencyCode());
097    }
098
099    /* (non-Javadoc)
100     * @see java.lang.Object#hashCode()
101     */
102    @Override
103    public int hashCode(){
104        return Objects.hashCode(currencyCode);
105    }
106
107    /* (non-Javadoc)
108     * @see java.lang.Object#equals(java.lang.Object)
109     */
110    @Override
111        public boolean equals(Object obj) {
112        if (obj == this) {
113            return true;
114        }
115        if (obj instanceof BuildableCurrencyUnit) {
116                 BuildableCurrencyUnit other = (BuildableCurrencyUnit) obj;
117                 return Objects.equals(currencyCode, other.currencyCode);
118        }
119        return false;
120    }
121
122    /* (non-Javadoc)
123     * @see java.lang.Object#toString()
124     */
125    @Override
126    public String toString(){
127        return "BuildableCurrencyUnit(currencyCode=" + currencyCode + ", numericCode=" + numericCode +
128                ", defaultFractionDigits=" + defaultFractionDigits + ", context="+this.currencyContext+")";
129    }
130
131
132    /**
133     * Builder for constructing new instances o{@link org.javamoney.moneta.BuildableCurrencyUnit} using a fluent
134     * API.
135     */
136    public static final class Builder{
137        /**
138         * The currency code.
139         */
140        private String currencyCode;
141        /**
142         * The (optional) numeric code.
143         */
144        private int numericCode = -1;
145        /**
146         * The default fraction digits.
147         */
148        private int defaultFractionDigits = 2;
149        /**
150         * THe currency's context.
151         */
152        private javax.money.CurrencyContext currencyContext;
153
154        /**
155         * Creats a new Builder.
156         *
157         * @param currencyCode the (unique) and identifying currency code, not null.
158         */
159        public Builder(String currencyCode, javax.money.CurrencyContext currencyContext){
160            Objects.requireNonNull(currencyCode, "currencyCode required");
161            this.currencyCode = currencyCode;
162            Objects.requireNonNull(currencyContext, "currencyContext required");
163            this.currencyContext = currencyContext;
164        }
165
166        /**
167         * Allows to set the currency code, for creating multiple instances, using one Builder.
168         *
169         * @param currencyCode the (unique) and identifying currency code, not null.
170         * @return the Builder, for chaining.
171         * @see javax.money.CurrencyUnit#getCurrencyCode()
172         */
173        public Builder setCurrencyCode(String currencyCode){
174            Objects.requireNonNull(currencyCode, "currencyCode required");
175            this.currencyCode = currencyCode;
176            this.currencyContext = CurrencyContextBuilder.create(getClass().getSimpleName()).build();
177            return this;
178        }
179
180        /**
181         * Set the numeric code (optional).
182         *
183         * @param numericCode The numeric currency code, &gt;= -1. .1 hereby means <i>undefined</i>.
184         * @return the Builder, for chaining.
185         * @see javax.money.CurrencyUnit#getNumericCode()
186         */
187        public Builder setNumericCode(int numericCode){
188            if(numericCode < -1){
189                throw new IllegalArgumentException("numericCode must be >= -1");
190            }
191            this.numericCode = numericCode;
192            return this;
193        }
194
195        /**
196         * Set the default fraction digits.
197         *
198         * @param defaultFractionDigits the default fraction digits, &gt;= 0.
199         * @return the Builder, for chaining.
200         * @see javax.money.CurrencyUnit#getDefaultFractionDigits()
201         */
202        public Builder setDefaultFractionDigits(int defaultFractionDigits){
203            if(defaultFractionDigits < 0){
204                throw new IllegalArgumentException("defaultFractionDigits must be >= 0");
205            }
206            this.defaultFractionDigits = defaultFractionDigits;
207            return this;
208        }
209
210        /**
211         * Returns a new instance of {@link org.javamoney.moneta.BuildableCurrencyUnit}.
212         *
213         * @return the new CurrencyUnit instance.
214         * @throws MonetaryException if creation fails
215         */
216        public BuildableCurrencyUnit build(){
217            return build(false);
218        }
219
220        /**
221         * Returns a new instance of {@link org.javamoney.moneta.BuildableCurrencyUnit} and publishes it so it is
222         * accessible from the {@code MonetaryCurrencies} singleton.
223         *
224         * @param register if {@code true} the instance created is published so it is accessible from
225         *                 the {@code MonetaryCurrencies} singleton.
226         * @return the new CurrencyUnit instance.
227         * @see javax.money.MonetaryCurrencies#getCurrency(String, String...)
228         */
229        public BuildableCurrencyUnit build(boolean register){
230            BuildableCurrencyUnit cu = new BuildableCurrencyUnit(this);
231            if(register){
232                ConfigurableCurrencyUnitProvider.registerCurrencyUnit(cu);
233            }
234            return cu;
235        }
236
237        /**
238         * Returns a new instance of {@link org.javamoney.moneta.BuildableCurrencyUnit} and publishes it so it is
239         * accessible from the {@code MonetaryCurrencies} singleton.
240         *
241         * @param register if {@code true} the instance created is published so it is accessible from
242         *                 the {@code MonetaryCurrencies} singleton.
243         * @param locale   country Locale for making the currency for the given country.
244         * @return the new CurrencyUnit instance.
245         * @see javax.money.MonetaryCurrencies#getCurrency(String, String...)
246         * @see javax.money.MonetaryCurrencies#getCurrency(Locale, String...)
247         */
248        public BuildableCurrencyUnit build(boolean register, Locale locale){
249            BuildableCurrencyUnit cu = new BuildableCurrencyUnit(this);
250            if(register){
251                ConfigurableCurrencyUnitProvider.registerCurrencyUnit(cu);
252                ConfigurableCurrencyUnitProvider.registerCurrencyUnit(cu, locale);
253            }
254            return cu;
255        }
256    }
257
258}