All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.gyftedstore.currency.rates.cca.CurrencyConverterExchange Maven / Gradle / Ivy

There is a newer version: 1.0.12
Show newest version
package com.gyftedstore.currency.rates.cca;

import com.gyftedstore.currency.rates.ExchangeProvider;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.util.MimeTypeUtils;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

import javax.annotation.PostConstruct;
import java.util.*;

@Slf4j
public class CurrencyConverterExchange implements ExchangeProvider {

    public static final String PLUGIN_NAME = "CurrencyConverterAPI";
    private static final String QRY_FROM = "from";
    private static final String QRY_TO = "to";

    private final CurrencyConverterApiProperties config;
    private final WebClient client;
    private Set supportedCurrencies;

    public CurrencyConverterExchange(CurrencyConverterApiProperties config) {
        this.config = config;
        this.client = WebClient.builder()
                .baseUrl(config.getUrl())
                .defaultHeader(HttpHeaders.ACCEPT, MimeTypeUtils.APPLICATION_JSON_VALUE)
                .defaultUriVariables(config.getParams())
                .build();
    }

    @PostConstruct
    public void intializeCCA() {
        log.trace("refreshing currencies using {}...", PLUGIN_NAME);
        try {
            supportedCurrencies = Optional.ofNullable(client.get()
                    .uri("/currencies?apiKey={key}", config.getApiKey())
                    .retrieve()
                    .onStatus(HttpStatus::isError, this::propagateError)
                    .bodyToMono(CurrenciesResult.class)
                    .map(CurrenciesResult::getResults)
                    .map(Map::keySet)
                    .block())
                    .orElseGet(TreeSet::new);
            log.info("loaded '{}' exchange rates", supportedCurrencies.size());
        } catch (Exception ex) {
            log.error("error calling supported currencies API: {}", ex.getLocalizedMessage());
        }
    }

    @Data
    private static class CurrencyData {
        private String id;
        private String name;
    }

    @Data
    private static class CurrenciesResult {
        private Map results;
    }

    @Override
    public String getName() {
        return PLUGIN_NAME;
    }

    @Override
    public Double getRate(String from, String to) {
        log.debug("getting rate '{}:{}' using '{}' provider", from, to, PLUGIN_NAME);
        String pair = String.format("%s_%s", from, to);
        LinkedHashMap values = new LinkedHashMap<>(config.getParams());
        values.putIfAbsent(QRY_FROM, from);
        values.putIfAbsent(QRY_TO, to);
        try {
            return client.get()
                    .uri("/convert?compact={compact}&apiKey={key}&q={from}_{to}", values)
                    .retrieve()
                    .onStatus(HttpStatus::isError, this::propagateError)
                    .bodyToMono(new ParameterizedTypeReference>() {})
                    .block()
                    .get(pair);
        } catch (Exception ex) {
            log.error("error calling exchange API for pair {}: {}", pair, ex.getLocalizedMessage());
        }
        return null;
    }

    private Mono propagateError(ClientResponse clientResponse) {
        HttpStatus status = clientResponse.statusCode();
        return Mono.error(() -> new IllegalStateException(String.format("ERROR(%d) - %s", status.value(), status.getReasonPhrase())));
    }

    @Override
    public boolean supports(String delimiter) {
        return getName().equalsIgnoreCase(delimiter);
    }

    @Override
    public boolean isCurrencySupported(String currency) {
        return Optional.ofNullable(supportedCurrencies)
                .map(curr -> curr.contains(currency))
                .orElse(false);
    }

    public Set supportedCurrencies() {
        final var list = Optional.ofNullable(supportedCurrencies).orElse(Collections.emptySet());
        log.trace("{}: return list of {} supported currencies", getName(), list.size());
        return list;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy