# HG changeset patch
# User japod@localhost
# Date 1222768209 -7200
# Node ID 37c9921c653e4801c1696ba1a41af0111ada8424
# Parent 2864c6d744c0b220358efb4bacf48df53e23dfde
updating solution 04 to 1.5
diff -r 2864c6d744c0 -r 37c9921c653e task1/solution04/src/org/apidesign/apifest08/currency/ConverterImpl.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/task1/solution04/src/org/apidesign/apifest08/currency/ConverterImpl.java Tue Sep 30 11:50:09 2008 +0200
@@ -0,0 +1,159 @@
+package org.apidesign.apifest08.currency;
+
+
+import java.math.BigDecimal;
+import java.math.MathContext;
+import java.math.RoundingMode;
+import java.util.Currency;
+
+
+/**
+ * Convert between two currencies.
+ *
+ * @author D'Arcy Smith
+ * @version 1.0
+ */
+final class ConvertorImpl
+ implements Convertor
+{
+ /**
+ * The currency to cvonvert from.
+ */
+ private final Currency currencyA;
+
+ /**
+ * The currency to cvonvert from.
+ */
+ private final Currency currencyB;
+
+ /**
+ * The echange rate between a and b.
+ */
+ private final BigDecimal currencyARate;
+
+ /**
+ * The echange rate between b and a.
+ */
+ private final BigDecimal currencyBRate;
+
+ /**
+ * Constructs a convertor with the specified currencies.
+ *
+ * @param a the currency to convert from.
+ * @param aRate the exchage rage between from and to.
+ * @param b the currency to convert to.
+ * @param bRate the exchage rage between to and from.
+ * @throws IllegalArgumentException if either any of the arguments are null or if either rate <= 0.
+ */
+ public ConvertorImpl(final Currency a,
+ final BigDecimal aRate,
+ final Currency b,
+ final BigDecimal bRate)
+ {
+ if(a == null)
+ {
+ throw new IllegalArgumentException("a cannot be null");
+ }
+
+ if(b == null)
+ {
+ throw new IllegalArgumentException("b cannot be null");
+ }
+
+ if(aRate == null)
+ {
+ throw new IllegalArgumentException("aRate cannot be null");
+ }
+
+ if(bRate == null)
+ {
+ throw new IllegalArgumentException("bRate cannot be null");
+ }
+
+ if(aRate.compareTo(BigDecimal.ZERO) <= 0)
+ {
+ throw new IllegalArgumentException("aRate must be > 0, was: " + aRate);
+ }
+
+ if(bRate.compareTo(BigDecimal.ZERO) <= 0)
+ {
+ throw new IllegalArgumentException("bRate must be > 0, was: " + bRate);
+ }
+
+ currencyA = a;
+ currencyB = b;
+ currencyARate = aRate;
+ currencyBRate = bRate;
+ }
+
+ /**
+ * Convert an amount from one currency to another.
+ *
+ * @param from the currency to convert from.
+ * @param to the currency to convert to.
+ * @param amount the amount to convert.
+ * @return the converted amount.
+ * @throws IllegalArgumentException if any of the arguments are null.
+ * @throws InvalidConversionException if either from or to are not equal to the currencies passed to the constructor.
+ */
+ public BigDecimal convert(final Currency from,
+ final Currency to,
+ final BigDecimal amount)
+ throws InvalidConversionException
+ {
+ final BigDecimal result;
+
+ if(amount == null)
+ {
+ throw new IllegalArgumentException("amount cannot be null");
+ }
+
+ if(from == null)
+ {
+ throw new IllegalArgumentException("from cannot be null");
+ }
+
+ if(to == null)
+ {
+ throw new IllegalArgumentException("to cannot be null");
+ }
+
+ if(!(from.equals(currencyA)) && (!(from.equals(currencyB))))
+ {
+ throw new InvalidConversionException("cannot convert from: " + from.getCurrencyCode(), from, currencyA, currencyB);
+ }
+
+ if(!(to.equals(currencyA)) && (!(to.equals(currencyB))))
+ {
+ throw new InvalidConversionException("cannot convert to: " + to.getCurrencyCode(), to, currencyA, currencyB);
+ }
+
+ // converting between the same currency is no converstion at all.
+ if(from.equals(to))
+ {
+ result = amount;
+ }
+ else
+ {
+ final BigDecimal rateX;
+ final BigDecimal rateY;
+ final BigDecimal temp;
+
+ if(from.equals(currencyA))
+ {
+ rateX = currencyARate;
+ rateY = currencyBRate;
+ }
+ else
+ {
+ rateX = currencyBRate;
+ rateY = currencyARate;
+ }
+
+ temp = amount.divide(rateX, MathContext.DECIMAL32);
+ result = temp.multiply(rateY);
+ }
+
+ return (result.setScale(2, RoundingMode.HALF_DOWN));
+ }
+}
diff -r 2864c6d744c0 -r 37c9921c653e task1/solution04/src/org/apidesign/apifest08/currency/Convertor.java
--- a/task1/solution04/src/org/apidesign/apifest08/currency/Convertor.java Tue Sep 30 11:47:02 2008 +0200
+++ b/task1/solution04/src/org/apidesign/apifest08/currency/Convertor.java Tue Sep 30 11:50:09 2008 +0200
@@ -2,8 +2,6 @@
import java.math.BigDecimal;
-import java.math.MathContext;
-import java.math.RoundingMode;
import java.util.Currency;
@@ -13,93 +11,20 @@
* @author D'Arcy Smith
* @version 1.0
*/
-public final class Convertor
+public interface Convertor
{
/**
- * The currency to cvonvert from.
- */
- private final Currency currencyA;
-
- /**
- * The currency to cvonvert from.
- */
- private final Currency currencyB;
-
- /**
- * Constructs a convertor with the specified currencies.
+ * Convert an amount from one currency to another.
*
- * @param a the currency to convert from.
- * @param b the currency to convert to.
- * @throws IllegalArgumentException if either a or b are null.
- */
- public Convertor(final Currency a,
- final Currency b)
- {
- if(a == null)
- {
- throw new IllegalArgumentException("a cannot be null");
- }
-
- if(b == null)
- {
- throw new IllegalArgumentException("a cannot be null");
- }
-
- currencyA = a;
- currencyB = b;
- }
-
- /**
- * Convert from currency "b" to currency "a".
- *
+ * @param from the currency to convert from.
+ * @param to the currency to convert to.
* @param amount the amount to convert.
* @return the converted amount.
- * @throws IllegalArgumentException if amount is null.
+ * @throws IllegalArgumentException if any of the arguments are null.
+ * @throws InvalidConversionException if either from or to are not valid for the convertor.
*/
- public BigDecimal convertFrom(final BigDecimal amount)
- {
- final BigDecimal aInUSD;
- final BigDecimal bInUSD;
- final BigDecimal temp;
- final BigDecimal result;
-
- if(amount == null)
- {
- throw new IllegalArgumentException("amount cannot be null");
- }
-
- aInUSD = CurrencyValues.getValue(currencyA);
- bInUSD = CurrencyValues.getValue(currencyB);
- temp = amount.divide(bInUSD, MathContext.DECIMAL32);
- result = temp.multiply(aInUSD);
-
- return (result.setScale(2, RoundingMode.HALF_DOWN));
- }
-
- /**
- * Convert from currency "a" to currency "b".
- *
- * @param amount the amount to convert.
- * @return the converted amount.
- * @throws IllegalArgumentException if amount is null.
- */
- public BigDecimal convertTo(final BigDecimal amount)
- {
- final BigDecimal aInUSD;
- final BigDecimal bInUSD;
- final BigDecimal temp;
- final BigDecimal result;
-
- if(amount == null)
- {
- throw new IllegalArgumentException("amount cannot be null");
- }
-
- aInUSD = CurrencyValues.getValue(currencyA);
- bInUSD = CurrencyValues.getValue(currencyB);
- temp = amount.divide(aInUSD, MathContext.DECIMAL32);
- result = temp.multiply(bInUSD);
-
- return (result.setScale(2, RoundingMode.HALF_DOWN));
- }
+ BigDecimal convert(Currency from,
+ Currency to,
+ BigDecimal amount)
+ throws InvalidConversionException;
}
diff -r 2864c6d744c0 -r 37c9921c653e task1/solution04/src/org/apidesign/apifest08/currency/ConvertorFactory.java
--- a/task1/solution04/src/org/apidesign/apifest08/currency/ConvertorFactory.java Tue Sep 30 11:47:02 2008 +0200
+++ b/task1/solution04/src/org/apidesign/apifest08/currency/ConvertorFactory.java Tue Sep 30 11:50:09 2008 +0200
@@ -1,6 +1,7 @@
package org.apidesign.apifest08.currency;
import java.lang.ref.WeakReference;
+import java.math.BigDecimal;
import java.util.Currency;
import java.util.Map;
import java.util.WeakHashMap;
@@ -36,11 +37,16 @@
* must be acceptable to java.util.Currency.getInstance(String)
*
* @param a the currency to convert from.
+ * @param aRate the exchange rate for a to b.
* @param b the currency to convert to.
+ * @param bRate the echante rate for b to a.
* @return the convertor for the specified currencies.
+ * @throws IllegalArgumentException if any of the arguments are null.
*/
- public static Convertor getConvertor(final String a,
- final String b)
+ public static Convertor getConvertor(final String a,
+ final BigDecimal aRate,
+ final String b,
+ final BigDecimal bRate)
{
final Currency currencyA;
final Currency currencyB;
@@ -48,7 +54,7 @@
currencyA = Currency.getInstance(a);
currencyB = Currency.getInstance(b);
- convertor = getConvertor(currencyA, currencyB);
+ convertor = getConvertor(currencyA, aRate, currencyB, bRate);
return (convertor);
}
@@ -57,11 +63,16 @@
* Get the convertor for the specified currencies.
*
* @param a the currency to convert from.
+ * @param aRate the exchange rate for a to b.
* @param b the currency to convert to.
+ * @param bRate the echante rate for b to a.
* @return the convertor for the specified currencies.
+ * @throws IllegalArgumentException if either any of the arguments are null or if either rate <= 0.
*/
- public static Convertor getConvertor(final Currency a,
- final Currency b)
+ public static Convertor getConvertor(final Currency a,
+ final BigDecimal aRate,
+ final Currency b,
+ final BigDecimal bRate)
{
final String key;
Convertor convertor;
@@ -75,15 +86,25 @@
{
throw new IllegalArgumentException("b cannot be null");
}
+
+ if(aRate == null)
+ {
+ throw new IllegalArgumentException("aRate cannot be null");
+ }
+
+ if(bRate == null)
+ {
+ throw new IllegalArgumentException("bRate cannot be null");
+ }
- key = a.getCurrencyCode() + b.getCurrencyCode();
+ key = a.getCurrencyCode() + aRate + b.getCurrencyCode() + bRate;
// make sure that we don't try to overwrite one
synchronized(convertors)
{
if(!(convertors.containsKey(key)))
{
- convertor = new Convertor(a, b);
+ convertor = new ConvertorImpl(a, aRate, b, bRate);
convertors.put(key, new WeakReference(convertor));
}
}
diff -r 2864c6d744c0 -r 37c9921c653e task1/solution04/src/org/apidesign/apifest08/currency/InvalidConversionException.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/task1/solution04/src/org/apidesign/apifest08/currency/InvalidConversionException.java Tue Sep 30 11:50:09 2008 +0200
@@ -0,0 +1,82 @@
+package org.apidesign.apifest08.currency;
+
+
+import java.util.Currency;
+
+
+/**
+ * Thrown when a currency is invalid for a given Convertor.
+ *
+ * @author D'Arcy Smith
+ * @version 1.0
+ */
+public class InvalidConversionException
+ extends Exception
+{
+ /**
+ * The currency that was tried.
+ */
+ private final Currency badCurrency;
+
+ /**
+ * A currency that is valid for the Convertor.
+ */
+ private final Currency currencyA;
+
+ /**
+ * A currency that is valid for the Convertor.
+ */
+ private final Currency currencyB;
+
+ /**
+ * Construct a new InvalidConversionException wit the specified message.
+ *
+ * @param msg the message for getMessage.
+ * @param bad the currency that is not valid.
+ * @param a a valid currency.
+ * @param b a valid currency.
+ */
+ public InvalidConversionException(final String msg,
+ final Currency bad,
+ final Currency a,
+ final Currency b)
+ {
+ super(msg);
+
+ badCurrency = bad;
+ currencyA = a;
+ currencyB = b;
+ }
+
+ /**
+ * Get the currency that is not valid.
+ *
+ * @return the badCurrency
+ */
+ public Currency getBadCurrency()
+ {
+ return (badCurrency);
+ }
+
+ /**
+ * Get a currency that is valid.
+ *
+ * @return the currencyA passed to the constructor.
+ */
+ public Currency getCurrencyA()
+ {
+ return (currencyA);
+ }
+
+ /**
+ * Get a currency that is valid.
+ *
+ * @return the currencyB passed to the constructor.
+ */
+ public Currency getCurrencyB()
+ {
+ return (currencyB);
+ }
+
+
+}
\ No newline at end of file
diff -r 2864c6d744c0 -r 37c9921c653e task1/solution04/test/org/apidesign/apifest08/test/Task1Test.java
--- a/task1/solution04/test/org/apidesign/apifest08/test/Task1Test.java Tue Sep 30 11:47:02 2008 +0200
+++ b/task1/solution04/test/org/apidesign/apifest08/test/Task1Test.java Tue Sep 30 11:50:09 2008 +0200
@@ -1,10 +1,13 @@
package org.apidesign.apifest08.test;
+
import java.math.BigDecimal;
import java.util.Currency;
import junit.framework.TestCase;
import org.apidesign.apifest08.currency.Convertor;
import org.apidesign.apifest08.currency.ConvertorFactory;
+import org.apidesign.apifest08.currency.InvalidConversionException;
+
/** Finish the Convertor API, and then write bodies of methods inside
* of this class to match the given tasks. To fullfil your task, use the
@@ -13,6 +16,18 @@
* shall run without any runtime permissions.
*/
public class Task1Test extends TestCase {
+
+ private final static Currency CZK;
+ private final static Currency SKK;
+ private final static Currency USD;
+
+ static
+ {
+ CZK = Currency.getInstance("CZK");
+ SKK = Currency.getInstance("SKK");
+ USD = Currency.getInstance("USD");
+ }
+
public Task1Test(String testName) {
super(testName);
}
@@ -35,7 +50,7 @@
*/
public static Convertor createCZKtoUSD()
{
- return (ConvertorFactory.getConvertor("CZK", "USD"));
+ return (ConvertorFactory.getConvertor("CZK", BigDecimal.valueOf(17.0), "USD", BigDecimal.valueOf(1)));
}
/** Create convertor that understands two currencies, CZK and
@@ -48,12 +63,7 @@
*/
public static Convertor createSKKtoCZK()
{
- return (ConvertorFactory.getConvertor(Currency.getInstance("SKK"), Currency.getInstance("CZK")));
- }
-
- public static Convertor createUSDtoUSD()
- {
- return (ConvertorFactory.getConvertor(Currency.getInstance("USD"), Currency.getInstance("USD")));
+ return (ConvertorFactory.getConvertor(Currency.getInstance("SKK"), BigDecimal.valueOf(100), Currency.getInstance("CZK"), BigDecimal.valueOf(80)));
}
/** Use the convertor from createCZKtoUSD
method and do few conversions
@@ -65,17 +75,17 @@
// convert $5 to CZK using c:
// assertEquals("Result is 85 CZK");
- result = c.convertFrom(BigDecimal.valueOf(5));
+ result = c.convert(USD, CZK, BigDecimal.valueOf(5));
assertEquals(new BigDecimal("85.00"), result);
// convert $8 to CZK
// assertEquals("Result is 136 CZK");
- result = c.convertFrom(BigDecimal.valueOf(8));
+ result = c.convert(USD, CZK, BigDecimal.valueOf(8));
assertEquals(new BigDecimal("136.00"), result);
// convert 1003CZK to USD
// assertEquals("Result is 59 USD");
- result = c.convertTo(BigDecimal.valueOf(1003));
+ result = c.convert(CZK, USD, BigDecimal.valueOf(1003));
assertEquals(new BigDecimal("59.00"), result);
}
@@ -88,31 +98,87 @@
// convert 16CZK using c:
// assertEquals("Result is 20 SKK");
- result = c.convertFrom(BigDecimal.valueOf(16));
+ result = c.convert(CZK, SKK, BigDecimal.valueOf(16));
assertEquals(new BigDecimal("20.00"), result);
// convert 500SKK to CZK
// assertEquals("Result is 400 CZK");
- result = c.convertTo(BigDecimal.valueOf(500));
+ result = c.convert(SKK, CZK, BigDecimal.valueOf(500));
assertEquals(new BigDecimal("400.00"), result);
}
- /** Use the convertor from createSKKtoCZK
method and do few conversions
- * with it.
+ /**
+ * Verify that the CZK to USD convertor knows nothing about SKK.
*/
- public void testCurrencyUSDUSD() throws Exception {
- Convertor c = createUSDtoUSD();
- BigDecimal result;
+ public void testCannotConvertToSKKwithCZKUSDConvertor()
+ throws Exception
+ {
+ Convertor c = createCZKtoUSD();
- // convert 1USD using c:
- // assertEquals("Result is 1 USD");
- result = c.convertFrom(BigDecimal.valueOf(1));
- assertEquals(new BigDecimal("1.00"), result);
-
- // convert 500USD to USD
- // assertEquals("Result is 500 USD");
- result = c.convertTo(BigDecimal.valueOf(500));
- assertEquals(new BigDecimal("500.00"), result);
- }
+ try
+ {
+ // convert $5 to SKK, the API shall say this is not possible
+ c.convert(USD, SKK, BigDecimal.valueOf(5));
+ fail("cannot use the CZKtoUSD converter to convert to SKK");
+ }
+ catch(InvalidConversionException ex)
+ {
+ assertEquals("cannot convert to: SKK", ex.getMessage());
+ assertEquals(SKK, ex.getBadCurrency());
+ assertEquals(CZK, ex.getCurrencyA());
+ assertEquals(USD, ex.getCurrencyB());
+ }
+
+ try
+ {
+ // convert 500 SKK to CZK, the API shall say this is not possible
+ c.convert(SKK, CZK, BigDecimal.valueOf(5));
+ fail("cannot use the CZKtoUSD converter to convert from SKK");
+ }
+ catch(InvalidConversionException ex)
+ {
+ assertEquals("cannot convert from: SKK", ex.getMessage());
+ assertEquals(SKK, ex.getBadCurrency());
+ assertEquals(CZK, ex.getCurrencyA());
+ assertEquals(USD, ex.getCurrencyB());
+ }
+ }
+
+ /**
+ * Verify that the CZK to SKK convertor knows nothing about USD.
+ */
+ public void testCannotConvertToUSDwithSKKCZKConvertor()
+ throws Exception
+ {
+ Convertor c = createSKKtoCZK();
+
+ try
+ {
+ // convert $5 to SKK, the API shall say this is not possible
+ c.convert(USD, SKK, BigDecimal.valueOf(5));
+ fail("cannot use the CZKtoUSD converter to convert to SKK");
+ }
+ catch(InvalidConversionException ex)
+ {
+ assertEquals("cannot convert from: USD", ex.getMessage());
+ assertEquals(USD, ex.getBadCurrency());
+ assertEquals(SKK, ex.getCurrencyA());
+ assertEquals(CZK, ex.getCurrencyB());
+ }
+
+ try
+ {
+ // convert 500 CZK to USD, the API shall say this is not possible
+ c.convert(CZK, USD, BigDecimal.valueOf(500));
+ fail("cannot use the CZKtoUSD converter to convert from SKK");
+ }
+ catch(InvalidConversionException ex)
+ {
+ assertEquals("cannot convert to: USD", ex.getMessage());
+ assertEquals(USD, ex.getBadCurrency());
+ assertEquals(SKK, ex.getCurrencyA());
+ assertEquals(CZK, ex.getCurrencyB());
+ }
+ }
}