001/* 002 * Copyright (c) 2012, 2013, Credit Suisse (Anatole Tresch), Werner Keil. 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 * 016 * Contributors: Anatole Tresch - initial implementation. 017 */ 018package org.javamoney.moneta.spi; 019 020import java.util.ArrayList; 021import java.util.List; 022 023import javax.money.CurrencyUnit; 024import javax.money.convert.ConversionContext; 025import javax.money.convert.ExchangeRate; 026import javax.money.convert.ExchangeRateProvider; 027import javax.money.convert.ProviderContext; 028 029/** 030 * This class implements a {@link ExchangeRateProvider} that delegates calls to 031 * a collection of child {@link ExchangeRateProvider} instance. 032 * 033 * @author Anatole Tresch 034 */ 035public class CompoundRateProvider extends AbstractRateProvider { 036 /** The {@link ExchangeRateProvider} instances. */ 037 private final List<ExchangeRateProvider> providers = new ArrayList<ExchangeRateProvider>(); 038 039 /** 040 * Constructor. 041 * 042 * @param providerContext 043 * The {@link ProviderContext} this instance is providing. 044 * Providers added must return the same on 045 * {@link ProviderContext#getProviderName()}. 046 */ 047 public CompoundRateProvider(Iterable<ExchangeRateProvider> providers) { 048 super(createContext(providers)); 049 for (ExchangeRateProvider exchangeRateProvider : providers) { 050 addProvider(exchangeRateProvider); 051 } 052 } 053 054 private static ProviderContext createContext( 055 Iterable<ExchangeRateProvider> providers) { 056 StringBuilder providerName = new StringBuilder("Compound: "); 057 for (ExchangeRateProvider exchangeRateProvider : providers) { 058 providerName.append(exchangeRateProvider.getProviderContext() 059 .getProviderName()); 060 providerName.append(','); 061 } 062 providerName.setLength(providerName.length() - 1); 063 return new ProviderContext.Builder(providerName.toString()).create(); 064 } 065 066 /** 067 * Add an additional {@link ExchangeRateProvider} to the instance's delegate 068 * list. Hereby {@link ExchangeRateProvider#getExchangeRateType()} of the 069 * provider added must be equal to {@link #getExchangeRateType()}. 070 * 071 * @param prov 072 * The {@link ExchangeRateProvider} to be added, not {@code null} 073 * . 074 * @throws IllegalArgumentException 075 * if {@link ExchangeRateProvider#getExchangeRateType()} of the 076 * provider added is not equal to {@link #getExchangeRateType()} 077 * . 078 */ 079 private void addProvider(ExchangeRateProvider prov) { 080 if (prov == null) { 081 throw new IllegalArgumentException("ConversionProvider required."); 082 } 083 providers.add(prov); 084 } 085 086 /* 087 * (non-Javadoc) 088 * 089 * @see 090 * javax.money.convert.ExchangeRateProvider#getExchangeRate(javax.money. 091 * CurrencyUnit, javax.money.CurrencyUnit, 092 * javax.money.convert.ConversionContext) 093 */ 094 @Override 095 protected ExchangeRate getExchangeRateInternal(CurrencyUnit base, 096 CurrencyUnit term, ConversionContext context) { 097 for (ExchangeRateProvider prov : this.providers) { 098 if (prov.isAvailable(base, term, context)) { 099 ExchangeRate rate = prov.getExchangeRate(base, term, context); 100 if (rate != null) { 101 return rate; 102 } 103 } 104 } 105 return null; 106 } 107 108}