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.ConversionQuery; 019import javax.money.convert.ExchangeRate; 020import javax.money.convert.ExchangeRateProvider; 021import javax.money.convert.ProviderContext; 022import javax.money.convert.ProviderContextBuilder; 023import javax.money.convert.RateType; 024 025import java.util.*; 026 027/** 028 * This class implements a {@link ExchangeRateProvider} that delegates calls to 029 * a collection of child {@link ExchangeRateProvider} instance. 030 * 031 * @author Anatole Tresch 032 */ 033public class CompoundRateProvider extends AbstractRateProvider { 034 /** 035 * Kery used to store a list of child {@link javax.money.convert.ProviderContext} instances of the providers 036 * contained within this instance. 037 */ 038 public static final String CHILD_PROVIDER_CONTEXTS_KEY = "childProviderContexts"; 039 /** 040 * The {@link ExchangeRateProvider} instances. 041 */ 042 private final List<ExchangeRateProvider> providers = new ArrayList<>(); 043 044 /** 045 * Constructor. 046 * 047 * @param providers The collection of child {@link ExchangeRateProvider} 048 * instances this class delegates calls to. 049 */ 050 public CompoundRateProvider(Iterable<ExchangeRateProvider> providers) { 051 super(createContext(providers)); 052 for (ExchangeRateProvider exchangeRateProvider : providers) { 053 addProvider(exchangeRateProvider); 054 } 055 } 056 057 private static ProviderContext createContext(Iterable<ExchangeRateProvider> providers) { 058 Set<RateType> rateTypeSet = new HashSet<>(); 059 StringBuilder providerName = new StringBuilder("Compound: "); 060 List<ProviderContext> childContextList = new ArrayList<>(); 061 for (ExchangeRateProvider exchangeRateProvider : providers) { 062 childContextList.add(exchangeRateProvider.getContext()); 063 providerName.append(exchangeRateProvider.getContext().getProviderName()); 064 providerName.append(','); 065 rateTypeSet.addAll(exchangeRateProvider.getContext().getRateTypes()); 066 } 067 providerName.setLength(providerName.length() - 1); 068 069 ProviderContextBuilder builder = ProviderContextBuilder.of(providerName.toString(), rateTypeSet); 070 builder.set(CHILD_PROVIDER_CONTEXTS_KEY, childContextList); 071 return builder.build(); 072 } 073 074 /** 075 * Add an additional {@link ExchangeRateProvider} to the instance's delegate 076 * list. 077 * 078 * @param prov The {@link ExchangeRateProvider} to be added, not {@code null} 079 * . 080 * @throws java.lang.NullPointerException if the provider is null. 081 * . 082 */ 083 private void addProvider(ExchangeRateProvider prov) { 084 if(prov==null){ 085 throw new NullPointerException("ConversionProvider required."); 086 } 087 providers.add(prov); 088 } 089 090 /* 091 * (non-Javadoc) 092 * 093 * @see 094 * ExchangeRateProvider#getExchangeRate(org.javamoney.bp. 095 * CurrencyUnit, CurrencyUnit, 096 * ConversionContext) 097 */ 098 @Override 099 public ExchangeRate getExchangeRate(ConversionQuery conversionQuery) { 100 for (ExchangeRateProvider prov : this.providers) { 101 if (prov.isAvailable(conversionQuery)) { 102 ExchangeRate rate = prov.getExchangeRate(conversionQuery); 103 if (rate!=null) { 104 return rate; 105 } 106 } 107 } 108 return null; 109 } 110 111 112}