# HG changeset patch # User Jaroslav Tulach # Date 1224257958 -7200 # Node ID 4de3a4b5445a7cdc89e3012f7b5b733e04e3b215 # Parent bf7622ec1713c3d5ecc1cb2e78babbb011960609 solution 12, task4 diff -r bf7622ec1713 -r 4de3a4b5445a task4/solution12/src/org/apidesign/apifest08/currency/Convertor.java --- a/task4/solution12/src/org/apidesign/apifest08/currency/Convertor.java Fri Oct 17 17:35:52 2008 +0200 +++ b/task4/solution12/src/org/apidesign/apifest08/currency/Convertor.java Fri Oct 17 17:39:18 2008 +0200 @@ -1,7 +1,9 @@ package org.apidesign.apifest08.currency; import java.util.ArrayList; +import java.util.Calendar; import java.util.Currency; +import java.util.Date; import java.util.Hashtable; import java.util.List; @@ -18,9 +20,9 @@ */ public class Convertor { - private static Hashtable exchangeRates; + private static Hashtable> exchangeRates; - private List currencyConvertors; + private List exchangeRateInstances; /** * Constructor. Checks if all selected currencies are not null and has defined exchange rates for both @@ -30,7 +32,7 @@ * pair of currencies */ private Convertor(Currency[] currencies) throws UnknownConvertorException { - currencyConvertors = new ArrayList(); + exchangeRateInstances = new ArrayList(); for (Currency currency1 : currencies) { for (Currency currency2 : currencies) { @@ -43,9 +45,9 @@ if (!exchangeRates.containsKey(key)) { throw new UnknownConvertorException("Selected convertor (" + currency1.getCurrencyCode() + "->" + currency2.getCurrencyCode() + ") has not defined exchange rates!!!"); - } + } - currencyConvertors.add(key); + exchangeRateInstances.add(new ExchangeRateInstance(key, null, null)); } } } @@ -73,16 +75,35 @@ } if (exchangeRates == null) { - exchangeRates = new Hashtable(); + exchangeRates = new Hashtable>(); } String key12 = currency1.getCurrencyCode() + currency2.getCurrencyCode(); String key21 = currency2.getCurrencyCode() + currency1.getCurrencyCode(); double recountedRate = (unit / rate) * unit; - exchangeRates.put(key12, new ExchangeRate(currency1, currency2, rate, unit)); - exchangeRates.put(key21, new ExchangeRate(currency2, currency1, recountedRate, unit)); + exchangeRates.put(key12, addNewExchangeRate(key12, currency1, currency2, rate, unit, null, null)); + exchangeRates.put(key21, addNewExchangeRate(key21, currency2, currency1, recountedRate, unit, null, null)); + } + + public static Convertor limitExchangeRatesValidity(Convertor convertor, Date validFrom, Date validTo) { + if(convertor == null || validFrom == null || validTo == null) { + throw new ConvertorException("None of parameters of method limitExchangeRatesValidity should be null!!!"); + } + + List exchangeRateInstances = convertor.getExchangeRateInstances(); + for (ExchangeRateInstance exchangeRateInstance : exchangeRateInstances) { + // get actual convertor rates for actual validity + ExchangeRate actualExchangeRate = getExchangeRate(exchangeRateInstance.getKey(), exchangeRateInstance.getValidFrom(), exchangeRateInstance.getValidTo()); + // set new validity for theese rates + actualExchangeRate.setValidFrom(validFrom); + actualExchangeRate.setValidTo(validTo); + // and for selected currency convertor + exchangeRateInstance.setValidFrom(validFrom); + exchangeRateInstance.setValidTo(substractSecond(validTo)); + } + return convertor; } /** @@ -97,7 +118,7 @@ throw new ConvertorException("It's impossible to merge with null convertor!!!"); } - currencyConvertors.addAll(convertor.getCurrencyConvertors()); + exchangeRateInstances.addAll(convertor.getExchangeRateInstances()); return this; } @@ -152,7 +173,8 @@ } /** - * Decides the direction of conversion and returns instance of actual exchange rate. + * Decides the direction of conversion and returns actual exchange rate + * for selected currencies and actual moment. * @param actualCurrency * actual currency we want to convert * @return actual exchange rate of this convertor for selected currency @@ -162,8 +184,9 @@ String key = originalCurrency.getCurrencyCode() + newCurrency.getCurrencyCode(); - if(currencyConvertors.contains(key)) { - actualyUsedExchangeRate = exchangeRates.get(key); + ExchangeRateInstance exchangeRateInstance = findExchangeRateInstance(key); + if(exchangeRateInstance != null) { + actualyUsedExchangeRate = getExchangeRate(exchangeRateInstance.getKey(), exchangeRateInstance.getValidFrom(), exchangeRateInstance.getValidTo()); } else { throw new InvalidCurrencyException("This convertor could not be used for converting selected currencies (" + originalCurrency.getCurrencyCode() + "->" + newCurrency.getCurrencyCode() + ") !!!"); @@ -173,11 +196,102 @@ } /** + * Finds instance of exchange rate for actual instance of convertor and actual moment. + * @param key exchange rate instance key + * @return exchange rate instance + */ + private ExchangeRateInstance findExchangeRateInstance(String key) { + ExchangeRateInstance instance = null; + + Date now = new Date(); + for (ExchangeRateInstance item : exchangeRateInstances) { + if(item.getKey().equals(key) && item.getValidFrom() == null && item.getValidTo() == null) { + instance = item; + break; + } else if(item.getKey().equals(key) && item.getValidFrom().compareTo(now) <= 0 && item.getValidTo().compareTo(now) >= 0) { + instance = item; + break; + } + } + + return instance; + } + + + /** * Returns currency convertors for actual instance of convertor. * @return currency convertors for actual instance of convertor */ - List getCurrencyConvertors() { - return currencyConvertors; + private List getExchangeRateInstances() { + return exchangeRateInstances; + } + + private static ExchangeRate getExchangeRate(String key, Date validFrom, Date validTo) { + ExchangeRate exchangeRate = null; + + List currencyExchangeRates = exchangeRates.get(key); + for (ExchangeRate currencyExchangeRate : currencyExchangeRates) { + Date actValidFrom = currencyExchangeRate.getValidFrom(); + Date actValidTo = currencyExchangeRate.getValidTo(); + + if(actValidFrom == null && validFrom == null && actValidTo == null && validTo == null) { + exchangeRate = currencyExchangeRate; + break; + } else if(actValidFrom != null && validFrom != null && actValidTo != null && validTo != null && actValidFrom.compareTo(validFrom) <= 0 && actValidTo.compareTo(validTo) > 0) { + exchangeRate = currencyExchangeRate; + break; + } + } + + if(exchangeRate == null) { + throw new ConvertorException("Exchange rate for actual exchange rate instance not found!!!"); + } + + return exchangeRate; + } + + private static List addNewExchangeRate(String key, Currency currency1, Currency currency2, double rate, double unit, Date validFrom, Date validTo) { + List actualExchangeRates = new ArrayList(); + ExchangeRate newExchangeRate = null; + + if(exchangeRates.containsKey(key)) { + List rates = exchangeRates.get(key); + for (ExchangeRate exchangeRate : rates) { + if(exchangeRate.getValidFrom() == null && exchangeRate.getValidTo() == null && validFrom == null && validTo == null) { + newExchangeRate = exchangeRate; + break; + } else if(exchangeRate.getValidFrom() != null && exchangeRate.getValidTo() != null && validFrom != null && validTo != null) { + if(exchangeRate.getValidFrom().compareTo(validFrom) == 0 && exchangeRate.getValidTo().compareTo(validTo) == 0) { + newExchangeRate = exchangeRate; + break; + } + } + } + actualExchangeRates.addAll(rates); + } + + if(newExchangeRate == null) { + actualExchangeRates.add(new ExchangeRate(currency1, currency2, rate, unit, validFrom, validTo)); + } else { + newExchangeRate.setRate(rate); + newExchangeRate.setUnit(unit); + actualExchangeRates.add(newExchangeRate); + } + + return actualExchangeRates; + } + + /** + * Substracts one second from selected date. + * @param date date + * @return date -1s + */ + private static Date substractSecond(Date date) { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + calendar.set(Calendar.SECOND, -1); + + return calendar.getTime(); } } diff -r bf7622ec1713 -r 4de3a4b5445a task4/solution12/src/org/apidesign/apifest08/currency/ExchangeRate.java --- a/task4/solution12/src/org/apidesign/apifest08/currency/ExchangeRate.java Fri Oct 17 17:35:52 2008 +0200 +++ b/task4/solution12/src/org/apidesign/apifest08/currency/ExchangeRate.java Fri Oct 17 17:39:18 2008 +0200 @@ -1,35 +1,101 @@ -package org.apidesign.apifest08.currency; - -import java.util.Currency; - -public class ExchangeRate { - - private Currency originalCurrency; - private Currency newCurrency; - private double unit; - private double rate; - - public ExchangeRate(Currency originalCurrency, Currency newCurrency, double rate, double unit) { - this.newCurrency = newCurrency; - this.originalCurrency = originalCurrency; - this.rate = rate; - this.unit = unit; - } - - public Currency getOriginalCurrency() { - return originalCurrency; - } - - public Currency getNewCurrency() { - return newCurrency; - } - - public double getUnit() { - return unit; - } - - public double getRate() { - return rate; - } - -} +package org.apidesign.apifest08.currency; + +import java.util.Currency; +import java.util.Date; + +public class ExchangeRate { + + private Currency originalCurrency; + private Currency newCurrency; + private double unit; + private double rate; + private Date validFrom; + private Date validTo; + + public ExchangeRate(Currency originalCurrency, Currency newCurrency, double rate, double unit) { + this.newCurrency = newCurrency; + this.originalCurrency = originalCurrency; + this.rate = rate; + this.unit = unit; + } + + public ExchangeRate(Currency originalCurrency, Currency newCurrency, double rate, double unit, Date validFrom, Date validTo) { + this.newCurrency = newCurrency; + this.originalCurrency = originalCurrency; + this.rate = rate; + this.unit = unit; + this.validFrom = validFrom; + this.validTo = validTo; + } + + /** + * @return the originalCurrency + */ + public Currency getOriginalCurrency() { + return originalCurrency; + } + + /** + * @return the newCurrency + */ + public Currency getNewCurrency() { + return newCurrency; + } + + /** + * @return the unit + */ + public double getUnit() { + return unit; + } + + /** + * @param unit the unit to set + */ + public void setUnit(double unit) { + this.unit = unit; + } + + /** + * @return the rate + */ + public double getRate() { + return rate; + } + + /** + * @param rate the rate to set + */ + public void setRate(double rate) { + this.rate = rate; + } + + /** + * @return the validFrom + */ + public Date getValidFrom() { + return validFrom; + } + + /** + * @param validFrom the validFrom to set + */ + public void setValidFrom(Date validFrom) { + this.validFrom = validFrom; + } + + /** + * @return the validTo + */ + public Date getValidTo() { + return validTo; + } + + /** + * @param validTo the validTo to set + */ + public void setValidTo(Date validTo) { + this.validTo = validTo; + } + +} diff -r bf7622ec1713 -r 4de3a4b5445a task4/solution12/src/org/apidesign/apifest08/currency/ExchangeRateInstance.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/task4/solution12/src/org/apidesign/apifest08/currency/ExchangeRateInstance.java Fri Oct 17 17:39:18 2008 +0200 @@ -0,0 +1,53 @@ +package org.apidesign.apifest08.currency; + +import java.util.Date; + +public class ExchangeRateInstance { + + private String key; + private Date validFrom; + private Date validTo; + + public ExchangeRateInstance(String key, Date validFrom, Date validTo) { + super(); + this.key = key; + this.validFrom = validFrom; + this.validTo = validTo; + } + + /** + * @return the validFrom + */ + public Date getValidFrom() { + return validFrom; + } + + /** + * @param validFrom the validFrom to set + */ + public void setValidFrom(Date validFrom) { + this.validFrom = validFrom; + } + + /** + * @return the validTo + */ + public Date getValidTo() { + return validTo; + } + + /** + * @param validTo the validTo to set + */ + public void setValidTo(Date validTo) { + this.validTo = validTo; + } + + /** + * @return the key + */ + public String getKey() { + return key; + } + +} diff -r bf7622ec1713 -r 4de3a4b5445a task4/solution12/test/org/apidesign/apifest08/test/Task4Test.java --- a/task4/solution12/test/org/apidesign/apifest08/test/Task4Test.java Fri Oct 17 17:35:52 2008 +0200 +++ b/task4/solution12/test/org/apidesign/apifest08/test/Task4Test.java Fri Oct 17 17:39:18 2008 +0200 @@ -1,8 +1,11 @@ package org.apidesign.apifest08.test; +import java.text.SimpleDateFormat; +import java.util.Currency; import java.util.Date; import junit.framework.TestCase; import org.apidesign.apifest08.currency.Convertor; +import org.apidesign.apifest08.currency.exceptions.UnknownConvertorException; /** The exchange rates are not always the same. They are changing. However * as in order to predict the future, one needs to understand own past. That is @@ -45,57 +48,104 @@ * @return new convertor */ public static Convertor limitTo(Convertor old, Date from, Date till) { - return null; + return Convertor.limitExchangeRatesValidity(old, from, till); } public void testCompositionOfLimitedConvertors() throws Exception { - if (Boolean.getBoolean("ignore.failing")) { - // implement me! then delete this if statement - return; - } - - Date d1 = null; // 2008-10-01 0:00 GMT - Date d2 = null; // 2008-10-02 0:00 GMT - Date d3 = null; // 2008-10-03 0:00 GMT + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm zzz"); + Date d1 = format.parse("2008-10-01 00:00 GMT"); // 2008-10-01 0:00 GMT + Date d2 = format.parse("2008-10-02 00:00 GMT"); // 2008-10-02 0:00 GMT + Date d3 = format.parse("2008-10-03 00:00 GMT"); // 2008-10-03 0:00 GMT Convertor c = Task2Test.merge( limitTo(Task1Test.createCZKtoUSD(), d1, d2), limitTo(Task1Test.createSKKtoCZK(), d2, d3) ); + + Date now = new Date(); // convert $5 to CZK using c: - // cannot convert as no rate is applicable to current date + double result = 0; + boolean exceptionThrown = false; + try { + result = c.convert(5, Currency.getInstance("USD"), Currency.getInstance("CZK")); + } catch (Exception e) { + exceptionThrown = true; + } + + if(d1.compareTo(now) <= 0 && d2.compareTo(now) > 0) { + System.out.println("Result."); + assertEquals("Result is not 85 CZK.", 85d, result); + } else { + System.out.println("Exception."); + assertEquals("There is no Exception while using convertor at wrong day!", true, exceptionThrown); + } // convert $8 to CZK using c: - // cannot convert as no rate is applicable to current date + exceptionThrown = false; + try { + result = c.convert(8, Currency.getInstance("USD"), Currency.getInstance("CZK")); + } catch (Exception e) { + exceptionThrown = true; + } + + if(d1.compareTo(now) <= 0 && d2.compareTo(now) > 0) { + System.out.println("Result."); + assertEquals("Result is not 136 CZK.", 136d, result); + } else { + System.out.println("Exception."); + assertEquals("There is no Exception while using convertor at wrong day!", true, exceptionThrown); + } // convert 1003CZK to USD using c: - // cannot convert as no rate is applicable to current date + exceptionThrown = false; + try { + result = c.convert(1003, Currency.getInstance("CZK"), Currency.getInstance("USD")); + } catch (Exception e) { + exceptionThrown = true; + } + + if(d1.compareTo(now) <= 0 && d2.compareTo(now) > 0) { + System.out.println("Result."); + assertEquals("Result is not 59 USD.", 59d, result); + } else { + System.out.println("Exception."); + assertEquals("There is no Exception while using convertor at wrong day!", true, exceptionThrown); + } // convert 16CZK using c: - // cannot convert as no rate is applicable to current date + exceptionThrown = false; + try { + result = c.convert(16, Currency.getInstance("CZK"), Currency.getInstance("SKK")); + } catch (Exception e) { + exceptionThrown = true; + } + + if(d2.compareTo(now) <= 0 && d3.compareTo(now) > 0) { + System.out.println("Result."); + assertEquals("Result is not 20 SKK.", 20d, result); + } else { + System.out.println("Exception."); + assertEquals("There is no Exception while using convertor at wrong day!", true, exceptionThrown); + } // convert 500SKK to CZK using c: - // cannot convert as no rate is applicable to current date + exceptionThrown = false; + try { + result = c.convert(500, Currency.getInstance("SKK"), Currency.getInstance("CZK")); + } catch (Exception e) { + exceptionThrown = true; + } + + if(d2.compareTo(now) <= 0 && d3.compareTo(now) > 0) { + System.out.println("Result."); + assertEquals("Result is not 400 CZK.", 400d, result); + } else { + System.out.println("Exception."); + assertEquals("There is no Exception while using convertor at wrong day!", true, exceptionThrown); + } - // convert $5 to CZK using c at 2008-10-01 6:00 GMT: - // assertEquals("Result is 85 CZK"); - - // convert $8 to CZK using c at 2008-10-01 6:00 GMT: - // assertEquals("Result is 136 CZK"); - - // convert 1003CZK to USD using c at 2008-10-01 6:00 GMT: - // assertEquals("Result is 59 USD"); - - // convert 16CZK using c at 2008-10-02 9:00 GMT: - // assertEquals("Result is 20 SKK"); - - // convert 500SKK to CZK using c at 2008-10-02 9:00 GMT: - // assertEquals("Result is 400 CZK"); - - // convert 500SKK to CZK using c at 2008-10-01 6:00 GMT: - // cannot convert as no rate is applicable to current date } /** Create convertor that understands two currencies, CZK and @@ -104,18 +154,26 @@ * @return prepared convertor ready for converting SKK to CZK and CZK to SKK */ public static Convertor createSKKtoCZK2() { - return null; + // set exchange rates + Convertor.setConvertorRates(Currency.getInstance("SKK"), Currency.getInstance("CZK"), 90d, 100d); + + // create new instance + Convertor convertor = null; + try { + convertor = Convertor.getConvertorInstance(Currency.getInstance("SKK"), Currency.getInstance("CZK")); + } catch (UnknownConvertorException e) { + e.printStackTrace(); + } + + return convertor; } public void testDateConvetorWithTwoDifferentRates() throws Exception { - if (Boolean.getBoolean("ignore.failing")) { - // implement me! then delete this if statement - return; - } - Date d1 = null; // 2008-10-01 0:00 GMT - Date d2 = null; // 2008-10-02 0:00 GMT - Date d3 = null; // 2008-10-03 0:00 GMT + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm zzz"); + Date d1 = format.parse("2008-10-01 00:00 GMT"); // 2008-10-01 0:00 GMT + Date d2 = format.parse("2008-10-02 00:00 GMT"); // 2008-10-02 0:00 GMT + Date d3 = format.parse("2008-10-03 00:00 GMT"); // 2008-10-03 0:00 GMT Convertor c = Task2Test.merge( limitTo(createSKKtoCZK2(), d1, d2), @@ -127,6 +185,27 @@ // convert 500SKK to CZK using c at 2008-10-01 6:00 GMT: // assertEquals("Result is 450 CZK"); + Date now = new Date(); + + // convert 500SKK to CZK using c: + double result = 0; + boolean exceptionThrown = false; + try { + result = c.convert(500, Currency.getInstance("SKK"), Currency.getInstance("CZK")); + } catch (Exception e) { + exceptionThrown = true; + } + + if(d1.compareTo(now) <= 0 && d2.compareTo(now) > 0) { + System.out.println("\nResult"); + assertEquals("Result is not 450 CZK.", 450d, result); + } else if(d2.compareTo(now) <= 0 && d3.compareTo(now) > 0) { + System.out.println("\nResult"); + assertEquals("Result is not 400 CZK.", 400d, result); + } else { + System.out.println("\nException"); + assertEquals("There is no Exception while using convertor at wrong day!", true, exceptionThrown); + } } }