001package org.javamoney.moneta;
002
003import javax.money.CurrencyUnit;
004import javax.money.NumberValue;
005import javax.money.convert.ConversionContext;
006import javax.money.convert.ExchangeRate;
007import javax.money.convert.RateType;
008import java.util.ArrayList;
009import java.util.Arrays;
010import java.util.List;
011import java.util.Objects;
012
013/**
014 * Builder for creating new instances of {@link javax.money.convert.ExchangeRate}. Note that
015 * instances of this class are not thread-safe.
016 *
017 * @author Anatole Tresch
018 * @author Werner Keil
019 */
020public class ExchangeRateBuilder{
021
022    /**
023     * The {@link javax.money.convert.ConversionContext}.
024     */
025    ConversionContext conversionContext;
026    /**
027     * The base (source) currency.
028     */
029    CurrencyUnit base;
030    /**
031     * The term (target) currency.
032     */
033    CurrencyUnit term;
034    /**
035     * The conversion factor.
036     */
037    NumberValue factor;
038    /**
039     * The chain of invovled rates.
040     */
041    List<ExchangeRate> rateChain = new ArrayList<>();
042
043    /**
044     * Sets the exchange rate type
045     *
046     * @param rateType the {@link javax.money.convert.RateType} contained
047     */
048    public ExchangeRateBuilder(String provider, RateType rateType){
049        this(ConversionContext.of(provider, rateType));
050    }
051
052    /**
053     * Sets the exchange rate type
054     *
055     * @param context the {@link javax.money.convert.ConversionContext} to be applied
056     */
057    public ExchangeRateBuilder(ConversionContext context){
058        setContext(context);
059    }
060
061    /**
062     * Sets the exchange rate type
063     *
064     * @param rate the {@link javax.money.convert.ExchangeRate} to be applied
065     */
066    public ExchangeRateBuilder(ExchangeRate rate){
067        setContext(rate.getConversionContext());
068        setFactor(rate.getFactor());
069        setTerm(rate.getCurrency());
070        setBase(rate.getBaseCurrency());
071        setRateChain(rate.getExchangeRateChain());
072    }
073
074    /**
075     * Sets the base {@link javax.money.CurrencyUnit}
076     *
077     * @param base to base (source) {@link javax.money.CurrencyUnit} to be applied
078     * @return the builder instance
079     */
080    public ExchangeRateBuilder setBase(CurrencyUnit base){
081        this.base = base;
082        return this;
083    }
084
085    /**
086     * Sets the terminating (target) {@link javax.money.CurrencyUnit}
087     *
088     * @param term to terminating {@link javax.money.CurrencyUnit} to be applied
089     * @return the builder instance
090     */
091    public ExchangeRateBuilder setTerm(CurrencyUnit term){
092        this.term = term;
093        return this;
094    }
095
096    /**
097     * Sets the {@link javax.money.convert.ExchangeRate} chain.
098     *
099     * @param exchangeRates the {@link javax.money.convert.ExchangeRate} chain to be applied
100     * @return the builder instance
101     */
102    public ExchangeRateBuilder setRateChain(ExchangeRate... exchangeRates){
103        this.rateChain.clear();
104        if(Objects.nonNull(exchangeRates)){
105            this.rateChain.addAll(Arrays.asList(exchangeRates.clone()));
106        }
107        return this;
108    }
109
110    /**
111     * Sets the {@link javax.money.convert.ExchangeRate} chain.
112     *
113     * @param exchangeRates the {@link javax.money.convert.ExchangeRate} chain to be applied
114     * @return the builder instance
115     */
116    public ExchangeRateBuilder setRateChain(List<ExchangeRate> exchangeRates){
117        this.rateChain.clear();
118        if(Objects.nonNull(exchangeRates)){
119            this.rateChain.addAll(exchangeRates);
120        }
121        return this;
122    }
123
124
125    /**
126     * Sets the conversion factor, as the factor
127     * {@code base * factor = target}.
128     *
129     * @param factor the factor.
130     * @return The builder instance.
131     */
132    public ExchangeRateBuilder setFactor(NumberValue factor){
133        this.factor = factor;
134        return this;
135    }
136
137    /**
138     * Sets the provider to be applied.
139     *
140     * @param conversionContext the {@link javax.money.convert.ConversionContext}, not null.
141     * @return The builder.
142     */
143    public ExchangeRateBuilder setContext(ConversionContext conversionContext){
144        Objects.requireNonNull(conversionContext);
145        this.conversionContext = conversionContext;
146        return this;
147    }
148
149    /**
150     * Builds a new instance of {@link javax.money.convert.ExchangeRate}.
151     *
152     * @return a new instance of {@link javax.money.convert.ExchangeRate}.
153     * @throws IllegalArgumentException if the rate could not be built.
154     */
155    public ExchangeRate build(){
156        return new DefaultExchangeRate(this);
157    }
158
159    /**
160     * Initialize the {@link ExchangeRateBuilder} with an {@link javax.money.convert.ExchangeRate}. This is
161     * useful for creating a new rate, reusing some properties from an
162     * existing one.
163     *
164     * @param rate the base rate
165     * @return the Builder, for chaining.
166     */
167    public ExchangeRateBuilder setRate(ExchangeRate rate){
168        this.base = rate.getBaseCurrency();
169        this.term = rate.getCurrency();
170        this.conversionContext = rate.getConversionContext();
171        this.factor = rate.getFactor();
172        this.rateChain = rate.getExchangeRateChain();
173        this.term = rate.getCurrency();
174        return this;
175    }
176}