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.CurrencyUnit;
019import javax.money.MonetaryAmount;
020import javax.money.MonetaryOperator;
021import javax.money.convert.ConversionContext;
022import javax.money.convert.CurrencyConversion;
023import javax.money.convert.CurrencyConversionException;
024import javax.money.convert.ExchangeRate;
025import java.util.Objects;
026
027/**
028 * Abstract base class used for implementing currency conversion.
029 *
030 * @author Anatole Tresch
031 * @author Werner Keil
032 */
033public abstract class AbstractCurrencyConversion implements CurrencyConversion{
034
035    private CurrencyUnit termCurrency;
036    private ConversionContext conversionContext;
037
038    public AbstractCurrencyConversion(CurrencyUnit termCurrency, ConversionContext conversionContext){
039        Objects.requireNonNull(termCurrency);
040        Objects.requireNonNull(conversionContext);
041        this.termCurrency = termCurrency;
042        this.conversionContext = conversionContext;
043    }
044
045    /**
046     * Access the terminating {@link CurrencyUnit} of this conversion instance.
047     *
048     * @return the terminating {@link CurrencyUnit} , never {@code null}.
049     */
050    public CurrencyUnit getCurrency(){
051        return termCurrency;
052    }
053
054    /**
055     * Access the target {@link ConversionContext} of this conversion instance.
056     *
057     * @return the target {@link ConversionContext}.
058     */
059    public ConversionContext getConversionContext(){
060        return conversionContext;
061    }
062
063    /**
064     * Get the exchange rate type that this {@link MonetaryOperator} instance is
065     * using for conversion.
066     *
067     * @return the {@link ExchangeRate} to be used, or null, if this conversion
068     * is not supported (will lead to a
069     * {@link CurrencyConversionException}.
070     * @see #apply(MonetaryAmount)
071     */
072    @Override
073    public abstract ExchangeRate getExchangeRate(MonetaryAmount amount);
074
075    /*
076     * (non-Javadoc)
077     * @see javax.money.convert.CurrencyConversion#with(javax.money.convert.ConversionContext)
078     */
079    public abstract CurrencyConversion with(ConversionContext conversionContext);
080
081    /**
082     * Method that converts the source {@link MonetaryAmount} to an
083     * {@link MonetaryAmount} based on the {@link ExchangeRate} of this
084     * conversion.
085     *
086     * @param amount The source amount
087     * @return The converted amount, never null.
088     * @throws CurrencyConversionException if conversion failed, or the required data is not available.
089     * @see #getExchangeRate(MonetaryAmount)
090     */
091    public MonetaryAmount apply(MonetaryAmount amount){
092        ExchangeRate rate = getExchangeRate(amount);
093        if(Objects.isNull(rate) || !amount.getCurrency().equals(rate.getBaseCurrency())){
094            throw new CurrencyConversionException(amount.getCurrency(),
095                                                  Objects.isNull(rate) ? null : rate.getCurrency(), null);
096        }
097        return amount.multiply(rate.getFactor()).getFactory().setCurrency(rate.getCurrency()).create();
098    }
099
100
101    /*
102     * (non-Javadoc)
103     *
104     * @see java.lang.Object#toString()
105     */
106    @Override
107    public String toString(){
108        return getClass().getName() + " [MonetaryAmount -> MonetaryAmount" + "]";
109    }
110
111}