1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/task1/solution04/src/org/apidesign/apifest08/currency/CurrencyValues.java Sun Sep 28 14:12:38 2008 +0200
1.3 @@ -0,0 +1,122 @@
1.4 +package org.apidesign.apifest08.currency;
1.5 +
1.6 +
1.7 +import java.math.BigDecimal;
1.8 +import java.util.Currency;
1.9 +import java.util.HashMap;
1.10 +import java.util.Map;
1.11 +import java.util.Timer;
1.12 +import java.util.TimerTask;
1.13 +
1.14 +
1.15 +/**
1.16 + * Keeps track of the current value for each currency as USD.
1.17 + *
1.18 + * @author D'Arcy Smith
1.19 + * @version 1.0
1.20 + */
1.21 +class CurrencyValues
1.22 +{
1.23 + /**
1.24 + * The values expressed in USD.
1.25 + */
1.26 + private static Map<Currency, BigDecimal> values;
1.27 +
1.28 + /**
1.29 + * Update the values periodically
1.30 + */
1.31 + private static final Timer refresher;
1.32 +
1.33 + static
1.34 + {
1.35 + final Refresher refresherTask;
1.36 + final long delay;
1.37 +
1.38 + // load the map NOW! (don't use the scheduler to do it just because we want
1.39 + // to be 100% certain it is loaded before anything else can be called.
1.40 + refresh();
1.41 +
1.42 + refresherTask = new Refresher();
1.43 + refresher = new Timer("CurrencyValues Refresher", true);
1.44 +
1.45 + // update once an hour
1.46 + delay = 1000 * 60 * 60;
1.47 + refresher.scheduleAtFixedRate(refresherTask, delay, delay);
1.48 + }
1.49 +
1.50 + /**
1.51 + * Prevent accidental creation.
1.52 + */
1.53 + private CurrencyValues()
1.54 + {
1.55 + }
1.56 +
1.57 + /**
1.58 + * Refresh the currency values.
1.59 + */
1.60 + static void refresh()
1.61 + {
1.62 + Map<Currency, BigDecimal> newValues;
1.63 + Currency currency;
1.64 +
1.65 + newValues = new HashMap<Currency, BigDecimal>();
1.66 +
1.67 + // these would update from a data source, database, web service, something...
1.68 + currency = Currency.getInstance("USD");
1.69 + newValues.put(currency, BigDecimal.valueOf(1.0).setScale(2));
1.70 +
1.71 + currency = Currency.getInstance("CZK");
1.72 + newValues.put(currency, BigDecimal.valueOf(17.0));
1.73 +
1.74 + currency = Currency.getInstance("SKK");
1.75 + newValues.put(currency, BigDecimal.valueOf(21.25));
1.76 +
1.77 + // don't sycnhronize all of it because clients can use slightly out of
1.78 + // date information.
1.79 + synchronized(CurrencyValues.class)
1.80 + {
1.81 + values = newValues;
1.82 + }
1.83 + }
1.84 +
1.85 + /**
1.86 + * Get the value of the specified currency in USD.
1.87 + *
1.88 + * @param currency the corrency to get.
1.89 + * @return the value of the currency in USD.
1.90 + * @throws IllegalArgumentException if currency is null.
1.91 + */
1.92 + static BigDecimal getValue(final Currency currency)
1.93 + {
1.94 + final BigDecimal value;
1.95 +
1.96 + if(currency == null)
1.97 + {
1.98 + throw new IllegalArgumentException("currencyName cannot be null");
1.99 + }
1.100 +
1.101 + // make sure we are not updating the map right now
1.102 + synchronized(CurrencyValues.class)
1.103 + {
1.104 + value = values.get(currency);
1.105 + }
1.106 +
1.107 + return (value);
1.108 + }
1.109 +
1.110 + /**
1.111 + * Used to update the currency map periodically.
1.112 + */
1.113 + private static class Refresher
1.114 + extends TimerTask
1.115 + {
1.116 + /**
1.117 + * call the refresh method.
1.118 + */
1.119 + @Override
1.120 + public void run()
1.121 + {
1.122 + refresh();
1.123 + }
1.124 + }
1.125 +}