/**
* Copyright (C) 2015 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.strata.basics.currency;
import static com.opengamma.strata.collect.Guavate.toImmutableList;
import java.util.Arrays;
import java.util.List;
import java.util.Map.Entry;
import java.util.logging.Logger;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableMap;
import com.opengamma.strata.collect.io.IniFile;
import com.opengamma.strata.collect.io.PropertySet;
import com.opengamma.strata.collect.io.ResourceConfig;
/**
* Internal loader of currency and currency pair data.
* <p>
* This loads configuration files for {@link Currency} and {@link CurrencyPair}.
*/
final class CurrencyDataLoader {
/**
* The logger.
*/
private static final Logger log = Logger.getLogger(CurrencyDataLoader.class.getName());
/**
* INI file for currency data.
*/
private static final String CURRENCY_INI = "Currency.ini";
/**
* INI file for currency pair data.
*/
private static final String PAIR_INI = "CurrencyPair.ini";
/**
* INI file containing a list of general currency data.
* This in includes a list of currencies in priority order used to choose the base currency of the market
* convention pair for pairs that aren't configured in currency-pair.ini.
*/
private static final String CURRENCY_DATA_INI = "CurrencyData.ini";
// restricted constructor
private CurrencyDataLoader() {
}
//-------------------------------------------------------------------------
/**
* Loads the available currencies.
*
* @param loadHistoric whether to load the historic or active currencies
* @return the map of known currencies
*/
static ImmutableMap<String, Currency> loadCurrencies(boolean loadHistoric) {
try {
IniFile ini = ResourceConfig.combinedIniFile(ResourceConfig.orderedResources(CURRENCY_INI));
return parseCurrencies(ini, loadHistoric);
} catch (RuntimeException ex) {
// logging used because this is loaded in a static variable
log.severe(Throwables.getStackTraceAsString(ex));
// return an empty instance to avoid ExceptionInInitializerError
return ImmutableMap.of();
}
}
// parse currency info
private static ImmutableMap<String, Currency> parseCurrencies(IniFile ini, boolean loadHistoric) {
ImmutableMap.Builder<String, Currency> builder = ImmutableMap.builder();
for (Entry<String, PropertySet> entry : ini.asMap().entrySet()) {
String currencyCode = entry.getKey();
if (currencyCode.length() == 3 && Currency.CODE_MATCHER.matchesAllOf(currencyCode)) {
PropertySet properties = entry.getValue();
boolean isHistoric =
(properties.keys().contains("historic") && Boolean.parseBoolean(properties.value("historic")));
if (isHistoric == loadHistoric) {
Integer minorUnits = Integer.parseInt(properties.value("minorUnitDigits"));
String triangulationCurrency = properties.value("triangulationCurrency");
builder.put(currencyCode, new Currency(currencyCode, minorUnits, triangulationCurrency));
}
}
}
return builder.build();
}
//-------------------------------------------------------------------------
/**
* Loads the available currency pairs.
*
* @return the map of known currency pairs, where the value is the number of digits in the rate
*/
static ImmutableMap<CurrencyPair, Integer> loadPairs() {
try {
IniFile ini = ResourceConfig.combinedIniFile(ResourceConfig.orderedResources(PAIR_INI));
return parsePairs(ini);
} catch (RuntimeException ex) {
// logging used because this is loaded in a static variable
log.severe(Throwables.getStackTraceAsString(ex));
// return an empty instance to avoid ExceptionInInitializerError
return ImmutableMap.of();
}
}
// parse pair info
private static ImmutableMap<CurrencyPair, Integer> parsePairs(IniFile ini) {
ImmutableMap.Builder<CurrencyPair, Integer> builder = ImmutableMap.builder();
for (Entry<String, PropertySet> entry : ini.asMap().entrySet()) {
String pairStr = entry.getKey();
if (CurrencyPair.REGEX_FORMAT.matcher(pairStr).matches()) {
CurrencyPair pair = CurrencyPair.parse(pairStr);
PropertySet properties = entry.getValue();
Integer rateDigits = Integer.parseInt(properties.value("rateDigits"));
builder.put(pair, rateDigits);
}
}
return builder.build();
}
/**
* Loads the priority order of currencies, used to determine the base currency of the market convention pair
* for pairs that aren't explicitly configured.
*
* @return a map of currency to order
*/
static ImmutableMap<Currency, Integer> loadOrdering() {
try {
IniFile ini = ResourceConfig.combinedIniFile(ResourceConfig.orderedResources(CURRENCY_DATA_INI));
PropertySet section = ini.section("marketConventionPriority");
String list = section.value("ordering");
// The currency ordering is defined as a comma-separated list
List<Currency> currencies = Arrays.stream(list.split(","))
.map(String::trim)
.map(Currency::of)
.collect(toImmutableList());
ImmutableMap.Builder<Currency, Integer> orderBuilder = ImmutableMap.builder();
for (int i = 0; i < currencies.size(); i++) {
orderBuilder.put(currencies.get(i), i + 1);
}
return orderBuilder.build();
} catch (Exception ex) {
// logging used because this is loaded in a static variable
log.severe(Throwables.getStackTraceAsString(ex));
// return an empty instance to avoid ExceptionInInitializerError
return ImmutableMap.of();
}
}
}