| /** |
| * |
| * 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(); |
| } |
| } |
| } |