001/* 002 * CREDIT SUISSE IS WILLING TO LICENSE THIS SPECIFICATION TO YOU ONLY UPON THE 003 * CONDITION THAT YOU ACCEPT ALL OF THE TERMS CONTAINED IN THIS AGREEMENT. 004 * PLEASE READ THE TERMS AND CONDITIONS OF THIS AGREEMENT CAREFULLY. BY 005 * DOWNLOADING THIS SPECIFICATION, YOU ACCEPT THE TERMS AND CONDITIONS OF THE 006 * AGREEMENT. IF YOU ARE NOT WILLING TO BE BOUND BY IT, SELECT THE "DECLINE" 007 * BUTTON AT THE BOTTOM OF THIS PAGE. Specification: JSR-354 Money and Currency 008 * API ("Specification") Copyright (c) 2012-2014, Credit Suisse All rights 009 * reserved. 010 */ 011package org.javamoney.moneta.spi.base; 012 013import javax.money.CurrencyUnit; 014import javax.money.Monetary; 015import javax.money.convert.ConversionQuery; 016import javax.money.convert.ConversionQueryBuilder; 017import javax.money.convert.CurrencyConversion; 018import javax.money.convert.ExchangeRate; 019import javax.money.convert.ExchangeRateProvider; 020import java.util.Objects; 021 022/** 023 * This interface defines access to the exchange rates provided by a provider. 024 * The provider and its capabilities can be defined in arbitrary detail by the 025 * corresponding {@link javax.money.convert.ProviderContext}. 026 * Instances of this class must only provide conversion data for exact one provider, identified by 027 * {@link javax.money.convert.ProviderContext#getProviderName()}. 028 * 029 * When accessing ExchangeRateProvider instances or {@link javax.money.convert.CurrencyConversion} instances from the 030 * {@link javax.money.convert.MonetaryConversions} 031 * in many cases a chain of providers will be returned. It is the responsibility of the implementation code assembling 032 * the chain to 033 * establish a well defined coordination mechanism for evaluating the correct result. By default the first provider 034 * in the chain that returns a non null result determines the final result of a call. Nevertheless adapting the 035 * {@link javax.money.spi.MonetaryConversionsSingletonSpi} allows 036 * to implement also alternate strategies, e.g. honoring different priorities of providers as well. 037 * <p> 038 * Implementations of this interface are required to be thread save. 039 * <p> 040 * Implementations of this class must neither be immutable nor serializable. 041 * 042 * @author Anatole Tresch 043 * @author Werner Keil 044 */ 045public abstract class BaseExchangeRateProvider implements ExchangeRateProvider{ 046 047 /** 048 * Checks if an {@link javax.money.convert.ExchangeRate} between two {@link javax.money.CurrencyUnit} is 049 * available from this provider. This method should check, if a given rate 050 * is <i>currently</i> defined. 051 * 052 * @param conversionQuery the required {@link javax.money.convert.ConversionQuery}, not {@code null} 053 * @return {@code true}, if such an {@link javax.money.convert.ExchangeRate} is currently 054 * defined. 055 */ 056 public boolean isAvailable(ConversionQuery conversionQuery){ 057 Objects.requireNonNull(conversionQuery); 058 try{ 059 return conversionQuery.getProviderNames().isEmpty() || 060 conversionQuery.getProviderNames().contains(getContext().getProviderName()); 061 } 062 catch(Exception e){ 063 return false; 064 } 065 } 066 067 068 /** 069 * Access a {@link javax.money.convert.ExchangeRate} using the given currencies. The 070 * {@link javax.money.convert.ExchangeRate} may be, depending on the data provider, eal-time or 071 * deferred. This method should return the rate that is <i>currently</i> 072 * valid. 073 * 074 * @param base base {@link javax.money.CurrencyUnit}, not {@code null} 075 * @param term term {@link javax.money.CurrencyUnit}, not {@code null} 076 * @throws javax.money.convert.CurrencyConversionException If no such rate is available. 077 */ 078 public ExchangeRate getExchangeRate(CurrencyUnit base, CurrencyUnit term){ 079 Objects.requireNonNull(base, "Base Currency is null"); 080 Objects.requireNonNull(term, "Term Currency is null"); 081 return getExchangeRate(ConversionQueryBuilder.of().setBaseCurrency(base).setTermCurrency(term).build()); 082 } 083 084 /** 085 * Access a {@link javax.money.convert.CurrencyConversion} that can be applied as a 086 * {@link javax.money.MonetaryOperator} to an amount. 087 * 088 * @param term term {@link javax.money.CurrencyUnit}, not {@code null} 089 * @return a new instance of a corresponding {@link javax.money.convert.CurrencyConversion}, 090 * never {@code null}. 091 */ 092 public CurrencyConversion getCurrencyConversion(CurrencyUnit term){ 093 return getCurrencyConversion(ConversionQueryBuilder.of().setTermCurrency(term).build()); 094 } 095 096 /** 097 * Checks if an {@link javax.money.convert.ExchangeRate} between two {@link javax.money.CurrencyUnit} is 098 * available from this provider. This method should check, if a given rate 099 * is <i>currently</i> defined. 100 * 101 * @param base the base {@link javax.money.CurrencyUnit} 102 * @param term the term {@link javax.money.CurrencyUnit} 103 * @return {@code true}, if such an {@link javax.money.convert.ExchangeRate} is currently 104 * defined. 105 */ 106 public boolean isAvailable(CurrencyUnit base, CurrencyUnit term){ 107 return isAvailable(ConversionQueryBuilder.of().setBaseCurrency(base).setTermCurrency(term).build()); 108 } 109 110 111 /** 112 * Checks if an {@link javax.money.convert.ExchangeRate} between two {@link javax.money.CurrencyUnit} is 113 * available from this provider. This method should check, if a given rate 114 * is <i>currently</i> defined. 115 * 116 * @param baseCode the base currency code 117 * @param termCode the terminal/target currency code 118 * @return {@code true}, if such an {@link javax.money.convert.ExchangeRate} is currently 119 * defined. 120 * @throws javax.money.MonetaryException if one of the currency codes passed is not valid. 121 */ 122 public boolean isAvailable(String baseCode, String termCode){ 123 return isAvailable(Monetary.getCurrency(baseCode), Monetary.getCurrency(termCode)); 124 } 125 126 127 /** 128 * Access a {@link javax.money.convert.ExchangeRate} using the given currencies. The 129 * {@link javax.money.convert.ExchangeRate} may be, depending on the data provider, eal-time or 130 * deferred. This method should return the rate that is <i>currently</i> 131 * valid. 132 * 133 * @param baseCode base currency code, not {@code null} 134 * @param termCode term/target currency code, not {@code null} 135 * @return the matching {@link javax.money.convert.ExchangeRate}. 136 * @throws javax.money.convert.CurrencyConversionException If no such rate is available. 137 * @throws javax.money.MonetaryException if one of the currency codes passed is not valid. 138 */ 139 public ExchangeRate getExchangeRate(String baseCode, String termCode){ 140 return getExchangeRate(Monetary.getCurrency(baseCode), Monetary.getCurrency(termCode)); 141 } 142 143 144 /** 145 * The method reverses the {@link javax.money.convert.ExchangeRate} to a rate mapping from term 146 * to base {@link javax.money.CurrencyUnit}. Hereby the factor must <b>not</b> be 147 * recalculated as {@code 1/oldFactor}, since typically reverse rates are 148 * not symmetric in most cases. 149 * 150 * @return the matching reversed {@link javax.money.convert.ExchangeRate}, or {@code null}, if 151 * the rate cannot be reversed. 152 */ 153 public ExchangeRate getReversed(ExchangeRate rate){ 154 ConversionQuery reverseQuery = rate.getContext().toQueryBuilder().setBaseCurrency(rate.getCurrency()) 155 .setTermCurrency(rate.getBaseCurrency()).build(); 156 if(isAvailable(reverseQuery)){ 157 return getExchangeRate(reverseQuery); 158 } 159 return null; 160 } 161 162 163 /** 164 * Access a {@link javax.money.convert.CurrencyConversion} that can be applied as a 165 * {@link javax.money.MonetaryOperator} to an amount. 166 * 167 * @param termCode terminal/target currency code, not {@code null} 168 * @return a new instance of a corresponding {@link javax.money.convert.CurrencyConversion}, 169 * never {@code null}. 170 * @throws javax.money.MonetaryException if one of the currency codes passed is not valid. 171 */ 172 public CurrencyConversion getCurrencyConversion(String termCode){ 173 return getCurrencyConversion(Monetary.getCurrency(termCode)); 174 } 175 176}