001/* 002 * Copyright (c) 2012, 2013, Credit Suisse (Anatole Tresch), Werner Keil. Licensed under the Apache 003 * License, Version 2.0 (the "License"); you may not use this file except in compliance with the 004 * License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 005 * Unless required by applicable law or agreed to in writing, software distributed under the License 006 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 007 * or implied. See the License for the specific language governing permissions and limitations under 008 * the License. 009 */ 010package org.javamoney.moneta.spi; 011 012import java.math.BigDecimal; 013import java.util.Objects; 014 015import javax.money.CurrencyUnit; 016import javax.money.MonetaryAmount; 017import javax.money.MonetaryOperator; 018import javax.money.convert.ConversionContext; 019import javax.money.convert.CurrencyConversion; 020import javax.money.convert.CurrencyConversionException; 021import javax.money.convert.ExchangeRate; 022import javax.money.convert.ProviderContext; 023 024import org.javamoney.moneta.BuildableCurrencyUnit; 025 026/** 027 * Abstract base class used for implementing currency conversion. 028 * 029 * @author Anatole Tresch 030 * @author Werner Keil 031 */ 032public abstract class AbstractCurrencyConversion implements CurrencyConversion { 033 034 private CurrencyUnit termCurrency; 035 private ConversionContext conversionContext; 036 037 public AbstractCurrencyConversion(CurrencyUnit termCurrency, 038 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 getTermCurrency() { 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 * @see #apply(MonetaryAmount) 068 * @return the {@link ExchangeRate} to be used, or null, if this conversion 069 * is not supported (will lead to a 070 * {@link CurrencyConversionException}. 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.<br/> 085 * 086 * @see #getExchangeRate(MonetaryAmount) 087 * @param amount 088 * The source amount 089 * @return The converted amount, never null. 090 * @throws CurrencyConversionException 091 * if conversion failed, or the required data is not available. 092 */ 093 // safe conversion due to MonetaryAmount contract 094 @Override 095 @SuppressWarnings("unchecked") 096 public <T extends MonetaryAmount> T apply(T amount) { 097 ExchangeRate rate = getExchangeRate(amount); 098 if (rate == null || !amount.getCurrency().equals(rate.getBase())) { 099 throw new CurrencyConversionException(amount.getCurrency(), 100 rate == null ? null : rate.getTerm(), null); 101 } 102 return (T) amount 103 .getFactory() 104 .setCurrency(rate.getTerm()) 105 .setNumber( 106 amount.multiply(rate.getFactor()).getNumber() 107 .numberValue(BigDecimal.class)).create(); 108 } 109 110 111 /* 112 * (non-Javadoc) 113 * 114 * @see java.lang.Object#toString() 115 */ 116 @Override 117 public String toString() { 118 return getClass().getName() + " [MonetaryAmount -> MonetaryAmount" 119 + "]"; 120 } 121 122}