japod@6: package org.apidesign.apifest08.currency;
japod@6:
japod@33: import java.util.ArrayList;
japod@6: import java.util.Currency;
japod@20: import java.util.Hashtable;
japod@33: import java.util.List;
japod@20:
japod@20: import org.apidesign.apifest08.currency.exceptions.ConvertorException;
japod@20: import org.apidesign.apifest08.currency.exceptions.InvalidCurrencyException;
japod@20: import org.apidesign.apifest08.currency.exceptions.UnknownConvertorException;
japod@6:
japod@6: /**
japod@6: * This is the skeleton class for your API. You need to make it public, so it is accessible to your client code
japod@6: * (currently in Task1Test.java) file.
japod@6: *
japod@6: * Feel free to create additional classes or rename this one, just keep all the API and its implementation in this
japod@6: * package. Do not spread it outside to other packages.
japod@6: */
japod@6: public class Convertor {
japod@6:
japod@20: private static Hashtable exchangeRates;
japod@6:
japod@51: private List currencyConvertors;
japod@20:
japod@51: /**
japod@51: * Constructor. Checks if all selected currencies are not null and has defined exchange rates for both
japod@51: * directions.
japod@51: * @param currencies currencies for new instance of convertor
japod@51: * @throws UnknownConvertorException if there are not defined exchange rates for both directions for each
japod@51: * pair of currencies
japod@51: */
japod@51: private Convertor(Currency[] currencies) throws UnknownConvertorException {
japod@51: currencyConvertors = new ArrayList();
japod@51:
japod@51: for (Currency currency1 : currencies) {
japod@51: for (Currency currency2 : currencies) {
japod@51: if(currency1 == null || currency2 == null) {
japod@51: throw new ConvertorException("None of the currencies should be null!!!");
japod@51: }
japod@51:
japod@51: if(!currency1.getCurrencyCode().equals(currency2.getCurrencyCode())) {
japod@51: String key = currency1.getCurrencyCode() + currency2.getCurrencyCode();
japod@51: if (!exchangeRates.containsKey(key)) {
japod@51: throw new UnknownConvertorException("Selected convertor (" + currency1.getCurrencyCode() + "->"
japod@51: + currency2.getCurrencyCode() + ") has not defined exchange rates!!!");
japod@51: }
japod@51:
japod@51: currencyConvertors.add(key);
japod@51: }
japod@51: }
japod@51: }
japod@20: }
japod@20:
japod@20: /**
japod@20: * Sets convertor rate for selected currencies.
japod@20: * @param currency1
japod@20: * one of the currencies we want to convert to/from
japod@20: * @param currency2
japod@20: * the other currency
japod@20: * @param rate
japod@20: * exchange rate from currency1 to currency2
japod@20: * @param unit
japod@20: * unit of exchangeRate (USD->CZK - unit=1, you exchange one dollar, SKK->CZK unit=100, exchange rate is for
japod@20: * 100SKK)
japod@20: */
japod@20: public static void setConvertorRates(Currency currency1, Currency currency2, double rate, double unit) {
japod@20: if (currency1 == null || currency2 == null) {
japod@20: throw new ConvertorException("None of the currencies should be null!!!");
japod@20: }
japod@20:
japod@20: if (rate <= 0 || unit <= 0) {
japod@20: throw new ConvertorException("Rate(" + rate + ") and unit(" + unit + ") has to be grater then zero!!!");
japod@20: }
japod@20:
japod@20: if (exchangeRates == null) {
japod@20: exchangeRates = new Hashtable();
japod@20: }
japod@20:
japod@20: String key12 = currency1.getCurrencyCode() + currency2.getCurrencyCode();
japod@20: String key21 = currency2.getCurrencyCode() + currency1.getCurrencyCode();
japod@20: double recountedRate = (unit / rate) * unit;
japod@20:
japod@20: exchangeRates.put(key12, new ExchangeRate(currency1, currency2, rate, unit));
japod@20: exchangeRates.put(key21, new ExchangeRate(currency2, currency1, recountedRate, unit));
japod@20:
japod@6: }
japod@33:
japod@33: /**
japod@33: * Merge exchange rates of actual convertor with exchange rates from selected
japod@33: * convertor. If there are same currencies in both convertors, these from selected
japod@33: * convertor rewrites these in actual convertor.
japod@33: * @param convertor convertor to merge with actual one
japod@33: * @return convertor with merged exchange rates
japod@33: */
japod@33: public Convertor merge(Convertor convertor) {
japod@51: if(convertor == null) {
japod@51: throw new ConvertorException("It's impossible to merge with null convertor!!!");
japod@51: }
japod@51:
japod@51: currencyConvertors.addAll(convertor.getCurrencyConvertors());
japod@33: return this;
japod@33: }
japod@6:
japod@6: /**
japod@6: * Creates new instance of convertor.
japod@6: * @param currency1
japod@6: * one of the currencies we want to convert to/from
japod@6: * @param currency2
japod@6: * the other currency
japod@6: * @return new instance of convertor
japod@20: * @throws UnknownConvertorException
japod@20: * thrown if convertor for selected currencies has not been defined
japod@6: */
japod@33: public static Convertor getConvertorInstance(Currency... currencies) throws UnknownConvertorException {
japod@33: if(currencies.length < 2) {
japod@33: throw new ConvertorException("To get convertor instance, you have to select at least two currencies!!!");
japod@33: }
japod@33:
japod@51: return new Convertor(currencies);
japod@6: }
japod@6:
japod@6: /**
japod@6: * Converts selected amout of selected currency to other currency of this convertor instance.
japod@6: * @param amount
japod@6: * amount to convert
japod@20: * @param originalCurrency
japod@6: * currency of this amount
japod@20: * @param newCurrency
japod@20: * currency to which we want convert
japod@6: * @return converted amount
japod@20: * @throws InvalidCurrencyException
japod@20: * while one or both currencies doesn't fit for this convertor
japod@6: */
japod@20: public double convert(double amount, Currency originalCurrency, Currency newCurrency) throws InvalidCurrencyException {
japod@20: ExchangeRate actualyUsedExchangeRate = null;
japod@6:
japod@20: if (originalCurrency == null) {
japod@20: throw new ConvertorException("Original currency is null!!!");
japod@6: }
japod@6:
japod@20: if (newCurrency == null) {
japod@20: throw new ConvertorException("Destination currency is null!!!");
japod@6: }
japod@6:
japod@20: actualyUsedExchangeRate = getExchangeRate(originalCurrency, newCurrency);
japod@20:
japod@20: return countResult(actualyUsedExchangeRate, amount);
japod@6: }
japod@6:
japod@20: private double countResult(ExchangeRate actualyUsedExchangeRate, double amount) {
japod@20: return amount * actualyUsedExchangeRate.getRate() / actualyUsedExchangeRate.getUnit();
japod@6: }
japod@6:
japod@6: /**
japod@6: * Decides the direction of conversion and returns instance of actual exchange rate.
japod@6: * @param actualCurrency
japod@6: * actual currency we want to convert
japod@6: * @return actual exchange rate of this convertor for selected currency
japod@6: */
japod@20: private ExchangeRate getExchangeRate(Currency originalCurrency, Currency newCurrency) throws InvalidCurrencyException {
japod@20: ExchangeRate actualyUsedExchangeRate = null;
japod@33:
japod@33: String key = originalCurrency.getCurrencyCode() + newCurrency.getCurrencyCode();
japod@6:
japod@51: if(currencyConvertors.contains(key)) {
japod@51: actualyUsedExchangeRate = exchangeRates.get(key);
japod@20: } else {
japod@33: throw new InvalidCurrencyException("This convertor could not be used for converting selected currencies (" + originalCurrency.getCurrencyCode() + "->"
japod@20: + newCurrency.getCurrencyCode() + ") !!!");
japod@6: }
japod@6:
japod@20: return actualyUsedExchangeRate;
japod@6: }
japod@33:
japod@33: /**
japod@51: * Returns currency convertors for actual instance of convertor.
japod@51: * @return currency convertors for actual instance of convertor
japod@33: */
japod@51: List getCurrencyConvertors() {
japod@51: return currencyConvertors;
japod@6: }
japod@33:
japod@6: }