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