task4/solution13/src/org/apidesign/apifest08/currency/ExchangeRateProvider.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Sat, 11 Oct 2008 23:38:46 +0200
changeset 61 58ec6da75f6f
parent 58 task3/solution13/src/org/apidesign/apifest08/currency/ExchangeRateProvider.java@07c16ec15a25
child 63 20d332739f60
permissions -rw-r--r--
Copying structure for task4
     1 package org.apidesign.apifest08.currency;
     2 
     3 import java.math.BigDecimal;
     4 import java.util.Date;
     5 import java.util.HashMap;
     6 import java.util.Map;
     7 
     8 /**
     9  * Exchange rate provider. Provides  exchange rate for two currencies (method {@link #getExchangeRate(ConvertorCurrency, ConvertorCurrency)} ).
    10  * <p>
    11  * Several method can be created to create <code>ExchangeRateProvider</code>:
    12  * <ul>
    13  * <li>{@link #createExchangeRateProvider() } - create <em>simple</em> exchange rate provider using fixed echange rate.
    14  * <li>{@link #createExchangeRateProvider(IExchangeRateEngine) } - create exchange rate provider using custom {@link IExchangeRateEngine}.
    15  * </ul>
    16  * <p>
    17  * Date dependend exchange rate to be implemented.
    18  * 
    19  * @author arnostvalicek
    20  */
    21 public class ExchangeRateProvider {
    22 
    23     IExchangeRateEngine exrateEngine;
    24     
    25     /**
    26      * Simple constructor for <code>ExchangeRateProviderM</code> which can provide fixed exchange rate.
    27      * 
    28      * Describes conversion <em>from ONE</em> to <em>to ONE</em> currency.
    29      * 
    30      * @param fromValue From value. BigDecimal value, precision should be set to currency precision.
    31      * @param fromCurrency From currency.
    32      * @param toValue To value. BigDecimal value, precision should be set to currency precision.
    33      * @param toCurrency To currency.
    34      * @deprecated deprecated since task2. Use {@link #createExchangeRateProvider() } instead of this constructor.
    35      */
    36     public ExchangeRateProvider(BigDecimal fromValue, ConvertorCurrency fromCurrency, BigDecimal toValue, ConvertorCurrency toCurrency) {
    37         this.exrateEngine = FixedOneExchangeRateEngine.createEngine(fromValue, fromCurrency, toValue, toCurrency);
    38     }
    39 
    40     private ExchangeRateProvider() {
    41     }
    42 
    43     /**
    44      * Static method to create new exchange rate provider. This exchange rate provider does not contain
    45      * any exchange rates (this is difference to public constructor).
    46      * @return New <code>ExchangeRateProvider</code>
    47      */
    48     public static ExchangeRateProvider createExchangeRateProvider() {
    49         ExchangeRateProvider provider = new ExchangeRateProvider();
    50         provider.exrateEngine = FixedExchangeRateEngine.createEngine();
    51         return provider;
    52     }
    53 
    54     /**
    55      * Static method to create exchange rate provider which is using provided <code>IExchangeRateEngine</code>. This exchange rate provider is using
    56      * <code>IExchangeRateEngine</code> to get actual exchange rate.
    57      * @param exchangeRateEngine <code>IExchangeRateEngine</code> used to get exchange rate.
    58      * @return Returns instance of <code>ExchangeRateProvider</code>
    59      */
    60     public static ExchangeRateProvider createExchangeRateProvider(IExchangeRateEngine exchangeRateEngine) {
    61         ExchangeRateProvider provider = new ExchangeRateProvider();
    62         provider.exrateEngine = exchangeRateEngine;
    63         return provider;
    64     }
    65 
    66     /**
    67      * Add new exchange rate to <code></code> to this <em>simple</em> exchange rate provider.
    68      * <p>
    69      * Example of specifiing conversion rate: 100 SKK == 80 CZK:<br>
    70      * <code>addFixedCurencyRate(ConvertorCurrency.getInstance("SKK"), new BigDecimal(100), ConvertorCurrency.getInstance("CZK"),  new BigDecimal(80));</code>
    71      * <p>
    72      * This method may be used <em>only</em> when <code>ExchangeRateProvider</code> is created using {@link #createExchangeRateProvider() } - creating exchange rate provider without external <code>IExchangeRateEngine</code>.
    73      * 
    74      * @param fromCurrency Source currency.
    75      * @param fromValue Valye for from currency.
    76      * @param toCurrency Target currency.
    77      * @param toValue Value for target currency.
    78      * @throws IllegalStateException Throws exception when adding fixed currency rate to exchange rate provider which is not created using {@link #createExchangeRateProvider() }.
    79      */
    80     public synchronized void addFixedCurencyRate(ConvertorCurrency fromCurrency, BigDecimal fromValue, ConvertorCurrency toCurrency, BigDecimal toValue) {
    81         if (exrateEngine instanceof FixedExchangeRateEngine) {
    82             ((FixedExchangeRateEngine) exrateEngine).addFixedCurencyRate(fromCurrency, fromValue, toCurrency, toValue);
    83         } else {
    84             throw new IllegalStateException("Cuurency rate can be added only to ExchangeRateProvider created with FixedExchangeRateEngine - using method createExchangeRateProvider()");
    85         }
    86     }
    87 
    88     /**
    89      * Get fixed exange rate for currencies (from->to).
    90      * @return Returns exchange rate.
    91      * @deprecated deprecated since task2. Use {@link #getExchangeRate(ConvertorCurrency, ConvertorCurrency) }
    92      */
    93     public ExchangeRate getExchangeRate() {
    94         //works only for FixedExchangeRateEngine
    95         if (exrateEngine instanceof FixedOneExchangeRateEngine) {
    96             FixedOneExchangeRateEngine engine = (FixedOneExchangeRateEngine) exrateEngine;
    97             return new ExchangeRate(engine.getFromValue(), engine.getToValue());
    98         } else {
    99             throw new IllegalStateException("Method supported only for MinimalFixedExchangeRateEngine. This method is deprecated");
   100         }
   101 
   102     }
   103 
   104     /**
   105      * Get fixed exange rate for currencies (from->to).
   106      * @return Returns exchange rate or <code>null</code> if exchange rate not found.
   107      */
   108     public ExchangeRate getExchangeRate(ConvertorCurrency fromCurrency, ConvertorCurrency toCurrency) {
   109         return getExchangeRateImpl(fromCurrency, toCurrency);
   110     }
   111 
   112     /**
   113      * Get fixed exange rate for currencies (from->to) or reversed exchange rate (to->from).
   114      * @return Returns exchange rate or <code>null</code> if exchange rate not found.
   115      */
   116     public ExchangeRate getReversibleExchangeRate(ConvertorCurrency fromCurrency, ConvertorCurrency toCurrency) {
   117         ExchangeRate rate = getExchangeRateImpl(fromCurrency, toCurrency);
   118         if (rate == null) {
   119             ExchangeRate revertedRate = getExchangeRateImpl(toCurrency, fromCurrency);
   120             if (revertedRate != null) {
   121                 rate = ExchangeRate.createRevertedRate(revertedRate);
   122             }
   123         }
   124         return rate;
   125     }
   126 
   127     /**
   128      * Get exchange rate for currencies (from->to) based on provided date.
   129      * @param date Date for which exchange rate should be provided.
   130      * @return Returns exchange rate 
   131      * @deprecated deprecated since task2. No real implementation in version2.
   132      */
   133     public ExchangeRate getExchangeRate(Date date) {
   134         //works only for FixedExchangeRateEngine
   135         if (exrateEngine instanceof FixedOneExchangeRateEngine) {
   136             FixedOneExchangeRateEngine engine = (FixedOneExchangeRateEngine) exrateEngine;
   137             return new ExchangeRate(engine.getFromValue(), engine.getToValue());
   138         } else {
   139             throw new IllegalStateException("Method supported only for FixedOneExchangeRateEngine. This method is deprecated");
   140         }
   141     }
   142 
   143     ConvertorCurrency getFromCurrency() {
   144         if (exrateEngine instanceof FixedOneExchangeRateEngine) {
   145             FixedOneExchangeRateEngine engine = (FixedOneExchangeRateEngine) exrateEngine;
   146             return engine.getFromCurrency();
   147         } else {
   148             throw new IllegalStateException("Method supported only for FixedOneExchangeRateEngine. This method is deprecated");
   149         }
   150     }
   151 
   152     ConvertorCurrency getToCurrency() {
   153         if (exrateEngine instanceof FixedOneExchangeRateEngine) {
   154             FixedOneExchangeRateEngine engine = (FixedOneExchangeRateEngine) exrateEngine;
   155             return engine.getToCurrency();
   156         } else {
   157             throw new IllegalStateException("Method supported only for FixedOneExchangeRateEngine. This method is deprecated");
   158         }
   159     }
   160 
   161     private ExchangeRate getExchangeRateImpl(ConvertorCurrency fromCurrency, ConvertorCurrency toCurrency) {
   162         ExchangeRate result = exrateEngine.getExchangeRate(fromCurrency, toCurrency);
   163         return result;
   164     }
   165 
   166     private static class FixedOneExchangeRateEngine implements IExchangeRateEngine {
   167 
   168         BigDecimal fromValue;
   169         ConvertorCurrency fromCurrency;
   170         BigDecimal toValue;
   171         ConvertorCurrency toCurrency;
   172 
   173         private FixedOneExchangeRateEngine(BigDecimal fromValue, ConvertorCurrency fromCurrency, BigDecimal toValue, ConvertorCurrency toCurrency) {
   174             this.fromValue = fromValue;
   175             this.toValue = toValue;
   176             this.fromCurrency = fromCurrency;
   177             this.toCurrency = toCurrency;
   178         }
   179 
   180         /**
   181          * Create IExchangeRateEngine conveting from <code>fromCurrency</code> to <code>toCurrency</code>
   182          * with echange rate <code>fromValue:toValue</code>
   183          * @param fromValue
   184          * @param fromCurrency
   185          * @param toValue
   186          * @param toCurrency
   187          * @return Returns instance of <code>FixedOneExchangeRateEngine</code>.
   188          */
   189         private static IExchangeRateEngine createEngine(BigDecimal fromValue, ConvertorCurrency fromCurrency, BigDecimal toValue, ConvertorCurrency toCurrency) {
   190             return new FixedOneExchangeRateEngine(fromValue, fromCurrency, toValue, toCurrency);
   191         }
   192 
   193         private BigDecimal getFromValue() {
   194             return fromValue;
   195         }
   196 
   197         private BigDecimal getToValue() {
   198             return toValue;
   199         }
   200 
   201         private ConvertorCurrency getFromCurrency() {
   202             return fromCurrency;
   203         }
   204 
   205         private ConvertorCurrency getToCurrency() {
   206             return toCurrency;
   207         }
   208 
   209         public ExchangeRate getExchangeRate(ConvertorCurrency fromCurrency, ConvertorCurrency toCurrency) {
   210             if (!fromCurrency.equals(this.fromCurrency)) {
   211                 return null;
   212             }
   213             if (!toCurrency.equals(this.toCurrency)) {
   214                 return null;
   215             }
   216             return new ExchangeRate(fromValue, toValue);
   217         }
   218     }
   219 
   220     /**
   221      * Exchange rate engine able to hold several fixed exchange rates.
   222      * 
   223      * @author arnostvalicek
   224      */
   225     private static class FixedExchangeRateEngine implements IExchangeRateEngine {
   226 
   227         private Map exchangeRateMap = new HashMap();
   228 
   229         private FixedExchangeRateEngine() {
   230         }
   231 
   232         /**
   233          * Create instance of <code>FixedExchangeRateEngine</code>.
   234          * @return Returns instance of <code>FixedExchangeRateEngine</code>.
   235          */
   236         public static IExchangeRateEngine createEngine() {
   237             return new FixedExchangeRateEngine();
   238         }
   239 
   240         public ExchangeRate getExchangeRate(ConvertorCurrency fromCurrency, ConvertorCurrency toCurrency) {
   241             Map map2 = (Map) exchangeRateMap.get(fromCurrency);
   242             if (map2 == null) {
   243                 return null;
   244             }
   245             ExchangeRate result = (ExchangeRate) map2.get(toCurrency);
   246             return result;
   247         }
   248 
   249         @SuppressWarnings("unchecked")
   250         public synchronized void addFixedCurencyRate(ConvertorCurrency fromCurrency, BigDecimal fromValue, ConvertorCurrency toCurrency, BigDecimal toValue) {
   251             if (fromValue == null) {
   252                 throw new NullPointerException("fromValue can't be null");
   253             }
   254             if (toValue == null) {
   255                 throw new NullPointerException("toValue can't be null");
   256             }
   257             Map map2 = (Map) exchangeRateMap.get(fromCurrency);
   258             if (map2 == null) {
   259                 map2 = new HashMap();
   260                 exchangeRateMap.put(fromCurrency, map2);
   261             }
   262 
   263             ExchangeRate rate = new ExchangeRate(fromValue, toValue);
   264             map2.put(toCurrency, rate);
   265         }
   266     }
   267 }