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