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