package org.javamoney.moneta.internal.convert.yahoo;
import java.io.InputStream;
import java.text.ParseException;
import java.time.LocalDate;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import javax.money.convert.ConversionContextBuilder;
import javax.money.convert.ExchangeRate;
import javax.money.convert.ProviderContext;
import javax.money.convert.RateType;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import org.javamoney.moneta.convert.ExchangeRateBuilder;
import org.javamoney.moneta.spi.DefaultNumberValue;
class YahooRateReadingHandler {
private final String YAHOO_DTO_PACKAGE = "org.javamoney.moneta.internal.convert.yahoo";
private final Map<LocalDate, Map<String, ExchangeRate>> excangeRates;
private final ProviderContext context;
public YahooRateReadingHandler(final Map<LocalDate, Map<String, ExchangeRate>> excangeRates,
final ProviderContext context) {
this.excangeRates = excangeRates;
this.context = context;
}
void parse(final InputStream stream) throws JAXBException, ParseException {
final Unmarshaller unmarshaller = JAXBContext.newInstance(YAHOO_DTO_PACKAGE).createUnmarshaller();
final YahooRoot root = (YahooRoot) unmarshaller.unmarshal(stream);
final YahooCurrencies currencies = root.getResources();
for (YahooQuoteItem quote : currencies.getResource()) {
YahooQuoteItemInformation information = YahooQuoteItemInformation.of(quote.getField());
if(!information.isCurrencyValid()) {
continue;
}
addRate(information);
}
}
private void addRate(YahooQuoteItemInformation information) {
final ExchangeRateBuilder builder = new ExchangeRateBuilder(
ConversionContextBuilder.create(context, RateType.DEFERRED).build());
builder.setBase(YahooAbstractRateProvider.BASE_CURRENCY);
builder.setTerm(information.getCurrency());
builder.setFactor(DefaultNumberValue.of(information.getValue()));
final ExchangeRate exchangeRate = builder.build();
Map<String, ExchangeRate> rateMap = this.excangeRates.get(information.getLocalDate());
if (Objects.isNull(rateMap)) {
synchronized (this.excangeRates) {
rateMap = Optional.ofNullable(this.excangeRates.get(information.getLocalDate())).orElse(new ConcurrentHashMap<>());
this.excangeRates.putIfAbsent(information.getLocalDate(), rateMap);
}
}
rateMap.put(information.getCurrency().getCurrencyCode(), exchangeRate);
}
}