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