All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.javamoney.moneta.convert.imf.IMFAbstractRateProvider Maven / Gradle / Ivy
/*
Copyright (c) 2012, 2015, Credit Suisse (Anatole Tresch), Werner Keil and others by the @author tag.
Licensed under the Apache License, Version 2.0 (the "License"); you may not
use this file except in compliance with the License. You may obtain a copy of
the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
License for the specific language governing permissions and limitations under
the License.
*/
package org.javamoney.moneta.convert.imf;
import java.io.InputStream;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.Comparator;
import java.util.Currency;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.money.CurrencyContextBuilder;
import javax.money.CurrencyUnit;
import javax.money.Monetary;
import javax.money.MonetaryException;
import javax.money.convert.ConversionContext;
import javax.money.convert.ConversionQuery;
import javax.money.convert.ExchangeRate;
import javax.money.convert.ProviderContext;
import org.javamoney.moneta.CurrencyUnitBuilder;
import org.javamoney.moneta.convert.ExchangeRateBuilder;
import org.javamoney.moneta.convert.imf.IMFRateReadingHandler.RateIMFResult;
import org.javamoney.moneta.spi.AbstractRateProvider;
import org.javamoney.moneta.spi.LoaderService.LoaderListener;
abstract class IMFAbstractRateProvider extends AbstractRateProvider implements LoaderListener {
private static final Logger LOG = Logger.getLogger(IMFAbstractRateProvider.class.getName());
static final Comparator COMPARATOR_EXCHANGE_BY_LOCAL_DATE = Comparator.comparing(c -> c.getContext().get(LocalDate.class));
static final String DEFAULT_USER_AGENT = "Chrome/51.0.2704.103";
protected static final Map CURRENCIES_BY_NAME = new HashMap<>();
protected static final CurrencyUnit SDR =
CurrencyUnitBuilder.of("SDR", CurrencyContextBuilder.of(IMFRateProvider.class.getSimpleName()).build())
.setDefaultFractionDigits(3).build(true);
protected Map> currencyToSdr = Collections.emptyMap();
protected Map> sdrToCurrency = Collections.emptyMap();
protected volatile String loadState;
protected volatile CountDownLatch loadLock = new CountDownLatch(1);
protected final IMFRateReadingHandler handler;
private final ProviderContext context;
public IMFAbstractRateProvider(ProviderContext providerContext) {
super(providerContext);
this.context = providerContext;
handler = new IMFRateReadingHandler(CURRENCIES_BY_NAME, context);
}
static {
for (Currency currency : Currency.getAvailableCurrencies()) {
CURRENCIES_BY_NAME.put(currency.getDisplayName(Locale.ENGLISH),
Monetary.getCurrency(currency.getCurrencyCode()));
}
CURRENCIES_BY_NAME.put("U.K. Pound Sterling", Monetary.getCurrency("GBP"));
CURRENCIES_BY_NAME.put("U.S. Dollar", Monetary.getCurrency("USD"));
CURRENCIES_BY_NAME.put("Bahrain Dinar", Monetary.getCurrency("BHD"));
CURRENCIES_BY_NAME.put("Botswana Pula", Monetary.getCurrency("BWP"));
CURRENCIES_BY_NAME.put("Czech Koruna", Monetary.getCurrency("CZK"));
CURRENCIES_BY_NAME.put("Icelandic Krona", Monetary.getCurrency("ISK"));
CURRENCIES_BY_NAME.put("Korean Won", Monetary.getCurrency("KRW"));
CURRENCIES_BY_NAME.put("Rial Omani", Monetary.getCurrency("OMR"));
CURRENCIES_BY_NAME.put("Nuevo Sol", Monetary.getCurrency("PEN"));
CURRENCIES_BY_NAME.put("Qatar Riyal", Monetary.getCurrency("QAR"));
CURRENCIES_BY_NAME.put("Saudi Arabian Riyal", Monetary.getCurrency("SAR"));
CURRENCIES_BY_NAME.put("Sri Lanka Rupee", Monetary.getCurrency("LKR"));
CURRENCIES_BY_NAME.put("Trinidad And Tobago Dollar", Monetary.getCurrency("TTD"));
CURRENCIES_BY_NAME.put("U.A.E. Dirham", Monetary.getCurrency("AED"));
CURRENCIES_BY_NAME.put("Peso Uruguayo", Monetary.getCurrency("UYU"));
CURRENCIES_BY_NAME.put("Bolivar Fuerte", Monetary.getCurrency("VEF"));
}
@Override
public void newDataLoaded(String resourceId, InputStream is) {
try {
int oldSize = this.sdrToCurrency.size();
RateIMFResult result = handler.read(is);
this.sdrToCurrency = result.getSdrToCurrency();
this.currencyToSdr = result.getCurrencyToSdr();
int newSize = this.sdrToCurrency.size();
loadState = "Loaded " + resourceId + " exchange rates for days:" + (newSize - oldSize);
LOG.info(loadState);
loadLock.countDown();
} catch (Exception e) {
loadState = "Last Error during data load: " + e.getMessage();
throw new IllegalArgumentException("Failed to load IMF data provided.", e);
}
}
@Override
public ExchangeRate getExchangeRate(ConversionQuery conversionQuery) {
try {
if (loadLock.await(30, TimeUnit.SECONDS)) {
if (currencyToSdr.isEmpty()) {
return null;
}
if (!isAvailable(conversionQuery)) {
return null;
}
CurrencyUnit base = conversionQuery.getBaseCurrency();
CurrencyUnit term = conversionQuery.getCurrency();
LocalDate[] times = getQueryDates(conversionQuery);
ExchangeRate rate1 = getExchangeRate(currencyToSdr.get(base), times);
ExchangeRate rate2 = getExchangeRate(sdrToCurrency.get(term), times);
if (base.equals(SDR)) {
return rate2;
} else if (term.equals(SDR)) {
return rate1;
}
if (Objects.isNull(rate1) || Objects.isNull(rate2)) {
return null;
}
ConversionContext context = getExchangeContext("imf.digit.fraction");
ExchangeRateBuilder builder =
new ExchangeRateBuilder(context);
builder.setBase(base);
builder.setTerm(term);
builder.setFactor(multiply(rate1.getFactor(), rate2.getFactor()));
builder.setRateChain(rate1, rate2);
return builder.build();
}else{
// Lets wait for a successful load only once, then answer requests as data is present.
loadLock.countDown();
throw new MonetaryException("Failed to load currency conversion data: " + loadState);
}
}
catch(InterruptedException e){
throw new MonetaryException("Failed to load currency conversion data: Load task has been interrupted.", e);
}
}
private ExchangeRate getExchangeRate(List rates,final LocalDate[] dates) {
if (Objects.isNull(rates) ) {
return null;
}
if (Objects.isNull(dates)) {
return rates.stream().sorted(COMPARATOR_EXCHANGE_BY_LOCAL_DATE.reversed()).findFirst().orElseThrow(() -> new MonetaryException("There is not more recent exchange rate to rate on IMFRateProvider."));
} else {
for (LocalDate localDate : dates) {
Predicate filter = rate -> rate.getContext().get(LocalDate.class).equals(localDate);
Optional exchangeRateOptional = rates.stream().filter(filter).findFirst();
if(exchangeRateOptional.isPresent()) {
return exchangeRateOptional.get();
}
}
String datesOnErros = Stream.of(dates).map(date -> date.format(DateTimeFormatter.ISO_LOCAL_DATE)).collect(Collectors.joining(","));
throw new MonetaryException("There is not exchange on day " + datesOnErros + " to rate to rate on IFMRateProvider.");
}
}
@Override
public String toString() {
String sb = getClass().getName() + '{' +
" context: " + context + '}';
return sb;
}
}