blob: df8ffe3932870fe8b5bb6c7908dcde3a2891594c [file] [log] [blame]
/**
*
* Copyright (c) 2011, 2016 - Loetz GmbH&Co.KG (69115 Heidelberg, Germany)
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Christophe Loetz (Loetz GmbH&Co.KG) - initial implementation
*/
package org.eclipse.osbp.utils.currency;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.Locale;
import org.joda.money.CurrencyUnit;
import org.joda.money.Money;
import org.joda.time.DateTime;
/**
* Currency Conversion
*/
public class CurrencyConverter {
private final Locale fLocalLocale;
private final CurrencyUnit fLocalCurrencyUnit;
private final BigDecimal fReferenceRateEuroToLocal;
private final Locale fForeignLocale;
private final CurrencyUnit fForeignCurrencyUnit;
private final BigDecimal fReferenceRateEuroToForeign;
private final DateTime fReferenceDate;
private final boolean fSameCurrencyUnit;
/**
* @param localLocale the local Locale
* @param foreignLocale the foreign Locale
* @param referenceDate the reference date used for reference rates
*/
public CurrencyConverter(final Locale localLocale, final Locale foreignLocale, final DateTime referenceDate) {
this(localLocale, null, foreignLocale, null, referenceDate);
}
/**
* @param localLocale the local Locale
* @param foreignCurrency the foreign Locale
* This constructor will use the actual reference dates aka "now"
*/
public CurrencyConverter(final Locale localLocale, final Locale foreignLocale) {
this(localLocale, foreignLocale, DateTime.now());
}
/**
* @param localLocale the local Locale
* @param localCurrency the local currency unit
* @param foreignLocale the foreign Locale
* @param foreignCurrency the foreign currency unit
* @param referenceDate the reference date used for reference rates
*/
public CurrencyConverter(final CurrencyUnit localCurrency, final CurrencyUnit foreignCurrency, final DateTime referenceDate) {
this(null, localCurrency, null, foreignCurrency, referenceDate);
}
/**
* @param localCurrency the local currency
* @param foreignCurrency the foreign currency
* This constructor will use the actual reference dates aka "now"
*/
public CurrencyConverter(final CurrencyUnit localUnit, final CurrencyUnit foreignCurrency) {
this(localUnit, foreignCurrency, DateTime.now());
}
private CurrencyConverter(final Locale localLocale, final CurrencyUnit localCurrency, final Locale foreignLocale, final CurrencyUnit foreignCurrency, final DateTime referenceDate) {
fLocalCurrencyUnit = currencyUnitOf(localLocale, localCurrency);
fLocalLocale = localeOf(localLocale, localCurrency);
fForeignCurrencyUnit = currencyUnitOf(foreignLocale, foreignCurrency);
fForeignLocale = localeOf(foreignLocale, foreignCurrency);
fSameCurrencyUnit = fLocalCurrencyUnit.equals(fForeignCurrencyUnit);
fReferenceDate = referenceDate;
fReferenceRateEuroToLocal = EuroBasedExchangeReferenceRates.getReferenceRate(fLocalCurrencyUnit, fReferenceDate);
fReferenceRateEuroToForeign = EuroBasedExchangeReferenceRates.getReferenceRate(fForeignCurrencyUnit, fReferenceDate);
}
/**
* @param locale
* @param currencyUnit
* @return the currency unit depending on either the currencyUnit or the locale
*/
public static CurrencyUnit currencyUnitOf(final Locale locale, final CurrencyUnit currencyUnit) {
if (currencyUnit == null) {
return CurrencyUnit.of(locale);
}
else {
return currencyUnit;
}
}
/**
* @param locale
* @param currencyUnit
* @return the locale depending on either the locale or the currencyUnit
*/
public static Locale localeOf(final Locale locale, final CurrencyUnit currencyUnit) {
if (locale == null) {
if (currencyUnit.getCountryCodes().size() == 1) {
return new Locale("", currencyUnit.getCountryCodes().iterator().next());
}
else {
return null;
}
}
else {
return locale;
}
}
/**
* @return the local Locale; may be null
*/
public Locale getLocalLocale() {
return fLocalLocale;
}
/**
* @return the local currency unit
*/
public CurrencyUnit getLocalCurrencyUnit() {
return fLocalCurrencyUnit;
}
/**
* @return the foreign Locale; may be null
*/
public Locale getForeignLocale() {
return fForeignLocale;
}
/**
* @return the foreign currency unit
*/
public CurrencyUnit getForeignCurrencyUnit() {
return fForeignCurrencyUnit;
}
/**
* @return the reference date used for reference rates
*/
public DateTime getReferenceDate() {
return fReferenceDate;
}
/**
* @return the rate from local to foreign currency
*/
public double getLocalToForeignReferenceRateAsDouble() {
return getLocalToForeignReferenceRate().doubleValue();
}
/**
* @return the rate from local to foreign currency
*/
public BigDecimal getLocalToForeignReferenceRate() {
return getReferenceRate(false);
}
/**
* @return the rate from foreign to local currency
*/
public double getForeignToLocalReferenceRateAsDouble() {
return getForeignToLocalReferenceRate().doubleValue();
}
/**
* @return the rate from foreign to local currency
*/
public BigDecimal getForeignToLocalReferenceRate() {
return getReferenceRate(true);
}
public final static MathContext BASIC_DIVIDE_RATES_MATHCONTEXT = new MathContext(8);
private BigDecimal getReferenceRate(boolean backward) {
if (backward) {
return fReferenceRateEuroToLocal.divide(fReferenceRateEuroToForeign, BASIC_DIVIDE_RATES_MATHCONTEXT);
}
else {
return fReferenceRateEuroToForeign.divide(fReferenceRateEuroToLocal, BASIC_DIVIDE_RATES_MATHCONTEXT);
}
}
/**
* @param localAmount
* @return the exchanged foreign amount
*/
public double exchangeToDouble(double localAmount) {
return exchangeToDouble(localAmount, false);
}
/**
* @param amount
* @param backward false if exchange from local to foreign currency, true vice versa
* @return the exchanged amount
*/
public double exchangeToDouble(double amount, boolean backward) {
return exchange(BigDecimal.valueOf(amount), backward).doubleValue();
}
/**
* @param localAmount
* @return the exchanged foreign amount
*/
public BigDecimal exchange(BigDecimal base) {
return exchange(base, false);
}
/**
* @param amount
* @param backward false if exchange from local to foreign currency, true vice versa
* @return the exchanged amount
*/
public BigDecimal exchange(BigDecimal base, boolean backward) {
if (fSameCurrencyUnit) {
return base;
}
else {
Money result;
if (backward) {
result = Money.of(
fLocalCurrencyUnit,
base
.multiply(fReferenceRateEuroToLocal)
.divide(fReferenceRateEuroToForeign, RoundingMode.HALF_EVEN),
RoundingMode.HALF_EVEN
);
}
else {
result = Money.of(
fForeignCurrencyUnit,
base
.multiply(fReferenceRateEuroToForeign)
.divide(fReferenceRateEuroToLocal, RoundingMode.HALF_EVEN),
RoundingMode.HALF_EVEN
);
}
return result.getAmount();
}
}
}