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.spi;
017
018import javax.money.convert.ConversionContext;
019import javax.money.convert.ConversionQuery;
020import javax.money.convert.CurrencyConversion;
021import javax.money.convert.ExchangeRate;
022import javax.money.convert.ProviderContext;
023import javax.money.convert.RateType;
024import org.javamoney.moneta.spi.base.BaseExchangeRateProvider;
025
026import javax.money.NumberValue;
027
028import java.math.BigDecimal;
029import java.math.MathContext;
030import java.math.RoundingMode;
031import java.util.Calendar;
032import java.util.Objects;
033import java.util.logging.Logger;
034
035/**
036 * Abstract base class for {@link javax.money.convert.ExchangeRateProvider} implementations.
037 *
038 * @author Anatole Tresch
039 * @author Werner Keil
040 */
041public abstract class AbstractRateProvider extends BaseExchangeRateProvider {
042
043    /**
044     * The logger used.
045     */
046    protected final Logger LOGGER = Logger.getLogger(getClass().getName());
047
048    /**
049     * The {@link javax.money.convert.ConversionContext} of this provider.
050     */
051    private final ProviderContext providerContext;
052
053    /**
054     * Constructor.
055     *
056     * @param providerContext the {@link ProviderContext}, not null.
057     */
058    public AbstractRateProvider(ProviderContext providerContext) {
059        this.providerContext = Objects.requireNonNull(providerContext);
060    }
061
062    /*
063     * (non-Javadoc)
064     *
065     * @see org.javamoney.bp.api.convert.spi.ExchangeRateProviderSpi#getExchangeRateType
066     * ()
067     */
068    @Override
069    public ProviderContext getContext() {
070        return providerContext;
071    }
072
073    @Override
074    public abstract ExchangeRate getExchangeRate(ConversionQuery conversionQuery);
075
076    @Override
077    public CurrencyConversion getCurrencyConversion(ConversionQuery conversionQuery) {
078        if (getContext().getRateTypes().size() == 1) {
079            return new LazyBoundCurrencyConversion(conversionQuery, this, ConversionContext
080                    .of(getContext().getProviderName(), getContext().getRateTypes().iterator().next()));
081        }
082        return new LazyBoundCurrencyConversion(conversionQuery, this,
083                ConversionContext.of(getContext().getProviderName(), RateType.ANY));
084    }
085
086
087    /**
088     * A protected helper method to multiply 2 {@link NumberValue} types.<br>
089     * If either of the values is <code>null</code> an {@link ArithmeticException} is thrown.
090     *
091     * @param multiplicand the first value to be multiplied
092     * @param multiplier   the second value to be multiplied
093     * @return the result of the multiplication as {@link NumberValue}
094     */
095    protected static NumberValue multiply(NumberValue multiplicand, NumberValue multiplier) {
096        if (multiplicand==null) {
097            throw new ArithmeticException("The multiplicand cannot be null");
098        }
099        if (multiplier==null) {
100            throw new ArithmeticException("The multiplier cannot be null");
101        }
102        return new DefaultNumberValue(
103                multiplicand.numberValueExact(BigDecimal.class).multiply(multiplier.numberValue(BigDecimal.class)));
104    }
105
106    /**
107     * A protected helper method to divide 2 {@link NumberValue} types.<br>
108     * If either of the values is <code>null</code> an {@link ArithmeticException} is thrown.
109     *
110     * @param dividend the first value to be divided
111     * @param divisor  the value to be divided by
112     * @return the result of the division as {@link NumberValue}
113     */
114    protected static NumberValue divide(NumberValue dividend, NumberValue divisor) {
115        if (dividend==null) {
116            throw new ArithmeticException("The dividend cannot be null");
117        }
118        if (divisor==null) {
119            throw new ArithmeticException("The divisor cannot be null");
120        }
121        return new DefaultNumberValue(
122                dividend.numberValueExact(BigDecimal.class).divide(divisor.numberValue(BigDecimal.class),
123                        RoundingMode.HALF_EVEN));
124    }
125
126    /**
127     * A protected helper method to divide 2 {@link NumberValue} types.<br>
128     * If either of the values is <code>null</code> an {@link ArithmeticException} is thrown.
129     *
130     * @param dividend the first value to be divided
131     * @param divisor  the value to be divided by
132     * @param context  the {@link MathContext} to use
133     * @return the result of the division as {@link NumberValue}
134     */
135    protected static NumberValue divide(NumberValue dividend, NumberValue divisor, MathContext context) {
136        if (dividend==null) {
137            throw new ArithmeticException("The dividend cannot be null");
138        }
139        if (divisor==null) {
140            throw new ArithmeticException("The divisor cannot be null");
141        }
142        return new DefaultNumberValue(
143                dividend.numberValueExact(BigDecimal.class).divide(divisor.numberValue(BigDecimal.class), context));
144    }
145
146    protected String formatLocalDate(Calendar calendar){
147        return calendar.get(Calendar.YEAR) + "-" + calendar.get(Calendar.MONTH) +
148                "-" + calendar.get(Calendar.DAY_OF_MONTH);
149    }
150}