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