task1/solution04/src/org/apidesign/apifest08/currency/CurrencyValues.java
changeset 6 97662396c0fd
     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 +}