package co.smartreceipts.android.model.gson;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Map;
import co.smartreceipts.android.model.PriceCurrency;
import co.smartreceipts.android.model.utils.ModelUtils;
/**
* <p>
* Tracks the exchange rate from a base currency to a set of other currencies. The base currency
* is defined in {@link #getBaseCurrency()} and can be exchanged to another currency via the rate
* from {@link #getExchangeRate(String)} or {@link #getExchangeRate(PriceCurrency)}.
* </p>
* <p>
* For example, if you had a price defined in "EUR" (the base currency) and wished to exchange it
* to "USD", you could call {@link #getExchangeRate(String)} to find the exchange rate between the two (i.e
* the numbed for which the "EUR" price needs to be multiplied by to convert to "USD").
* </p>
*/
public class ExchangeRate implements Serializable {
private static final int PRECISION = 6;
private final String base;
private final Map<String, Double> rates;
public ExchangeRate(String base, Map<String, Double> rates) {
this.base = base;
this.rates = rates;
}
/**
* Gets the base currency for this exchange rate. All exchange rates will be compared against this.
*
* @return the base {@link PriceCurrency}
*/
@Nullable
public PriceCurrency getBaseCurrency() {
if (base == null) {
return null;
} else {
return PriceCurrency.getInstance(base);
}
}
/**
* Gets the base currency code for this exchange rate. All exchange rates will be compared against this.
*
* @return the base currency code as a {@link String}
*/
@Nullable
public String getBaseCurrencyCode() {
return base;
}
/**
* Tests if this exchange rate is properly defined in order to support an exchange rate for a given currency
*
* @param currency the {@link PriceCurrency} to test if we have a valid rate
* @return {@code true} if we have a valid exchange rate. {@code false} otherwise
*/
public boolean supportsExchangeRateFor(@NonNull PriceCurrency currency) {
return supportsExchangeRateFor(currency.getCurrencyCode());
}
/**
* Tests if this exchange rate is properly defined in order to support an exchange rate for a given currency
*
* @param currencyCode the currency code (e.g. "USD")to test if we have a valid rate
* @return {@code true} if we have a valid exchange rate or this is the same currency as the base one. {@code false} otherwise
*/
public boolean supportsExchangeRateFor(@NonNull String currencyCode) {
if (currencyCode.equalsIgnoreCase(base)) {
// We always support same currency exchange (i.e. "USD" -> "USD")
return true;
}
if (base == null || rates == null) {
return false;
} else {
if (rates.containsKey(currencyCode)) {
return rates.get(currencyCode) > 0;
} else {
return false;
}
}
}
/**
* Gets the exchange rate from the base currency to a currency of your choice
*
* @param exchangeCurrency the {@link PriceCurrency} to exchange to
* @return the exchange rate or {@code null} if we did not define one for this currency
*/
@Nullable
public BigDecimal getExchangeRate(@NonNull PriceCurrency exchangeCurrency) {
return getExchangeRate(exchangeCurrency.getCurrencyCode());
}
/**
* Gets the exchange rate from the base currency to a currency of your choice
*
* @param exchangeCurrencyCode the currency code (e.g. "USD") to exchange to
* @return the exchange rate or {@code null} if we did not define one for this currency code. If the
* desired currency is the same as base currency, the "1" will be returned.
*/
@Nullable
public BigDecimal getExchangeRate(@NonNull String exchangeCurrencyCode) {
if (exchangeCurrencyCode.equalsIgnoreCase(base)) {
// We always support same currency exchange (i.e. "USD" -> "USD")
return new BigDecimal(1);
}
if (supportsExchangeRateFor(exchangeCurrencyCode)) {
return new BigDecimal(rates.get(exchangeCurrencyCode));
} else {
return null;
}
}
/**
* A "decimal-formatted" price, which would appear to the end user as "25.20" or "25,20" instead of
* showing naively as "25.2"
*
* @param exchangeCurrency the {@link PriceCurrency} to exchange to
* @return the decimal exchange rate or an empty string if we did not define one for this currency
*/
@NonNull
public String getDecimalFormattedExchangeRate(@NonNull PriceCurrency exchangeCurrency) {
return getDecimalFormattedExchangeRate(exchangeCurrency.getCurrencyCode());
}
/**
* Gets the exchange rate from the base currency to a currency of your choice
*
* @param exchangeCurrencyCode the currency code (e.g. "USD") to exchange to
* @return the exchange rate or {@code null} if we did not define one for this currency code. If the
* desired currency is the same as base currency, the "1" will be returned.
*/
@NonNull
public String getDecimalFormattedExchangeRate(@NonNull String exchangeCurrencyCode) {
if (exchangeCurrencyCode.equalsIgnoreCase(base)) {
// We always support same currency exchange (i.e. "USD" -> "USD")
return ModelUtils.getDecimalFormattedValue(new BigDecimal(1), PRECISION);
}
if (supportsExchangeRateFor(exchangeCurrencyCode)) {
return ModelUtils.getDecimalFormattedValue(new BigDecimal(rates.get(exchangeCurrencyCode)), PRECISION);
} else {
return "";
}
}
@Override
public String toString() {
return "ExchangeRate{" + "base='" + base + '\'' + ", rates=" + rates + '}';
}
}