task2/solution10/src/org/apidesign/apifest08/currency/OfflineConverterProvider.java
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/task2/solution10/src/org/apidesign/apifest08/currency/OfflineConverterProvider.java Wed Oct 01 10:43:05 2008 +0200
1.3 @@ -0,0 +1,120 @@
1.4 +package org.apidesign.apifest08.currency;
1.5 +
1.6 +import java.util.*;
1.7 +
1.8 +/**
1.9 + * ConvertorProvider class is introduced to handle
1.10 + */
1.11 +public final class OfflineConverterProvider implements CurrencyConverterProvider {
1.12 +
1.13 +
1.14 + // we can't synchronize on DEFAULT as it's not final and can even be null in synchronized section
1.15 + private static final Object LOCK = new Object();
1.16 + private static CurrencyConverterProvider DEFAULT;
1.17 +
1.18 + // this is not nice and could be static, but future usage is uncertain and it's pretty easy to create
1.19 + private final Map<Currency, Double> rates;
1.20 +
1.21 + private OfflineConverterProvider() {
1.22 + rates = new HashMap<Currency, Double>();
1.23 + // simple initialization just for Task1Test
1.24 + rates.put(Currency.getInstance("USD"), 100.0);
1.25 + rates.put(Currency.getInstance("CZK"), 1700.0);
1.26 + rates.put(Currency.getInstance("SKK"), 2125.0);
1.27 + }
1.28 +
1.29 + /**
1.30 + * Provides default implementation of ConvertorProvider. This Converter does nos not ensure accuracy
1.31 + * of exchange rates, but should be functional at any circumstances including being offline.
1.32 + *
1.33 + * @return
1.34 + */
1.35 + public static CurrencyConverterProvider getInstance() {
1.36 + // should be necessary in current implementation as creating CurrencyConverterProvider is cheap, but for future
1.37 + if (DEFAULT == null)
1.38 + synchronized (LOCK) {
1.39 + if (DEFAULT == null)
1.40 + DEFAULT = new OfflineConverterProvider();
1.41 + }
1.42 + return DEFAULT;
1.43 + }
1.44 +
1.45 + @Override
1.46 + public CurrencyConverter getConverter(double amount1, /*@NotNull*/ String currency1,
1.47 + double amount2, /*@NotNull*/ String currency2)
1.48 + throws IllegalArgumentException {
1.49 +
1.50 + return getConverter(amount1, Currency.getInstance(currency2), amount2, Currency.getInstance(currency1));
1.51 + }
1.52 +
1.53 + /**
1.54 + * Retrieves converter that is capable of converting values between currency1 and currency2. The exchange is
1.55 + * specified in easy to understand way. By specifying values in two currencies that are equal. For example
1.56 + * CurrencyConverter.getConverter(25, "CZK", 1, "EUR"); means 25CKZ is equal to 1EUR. This enables user to
1.57 + * use this method without having to calculate anything. In general this can be expressed by formula
1.58 + * amount1[currency1] = amount2[currency2].
1.59 + *
1.60 + * @param amount1
1.61 + * @param currency1
1.62 + * @param amount2
1.63 + * @param currency2
1.64 + *
1.65 + * @return
1.66 + *
1.67 + * @throws IllegalArgumentException
1.68 + * @throws CurrencyNotAvailableException
1.69 + *
1.70 + */
1.71 + @Override
1.72 + public CurrencyConverter getConverter(double amount1, /*@NotNull*/ Currency currency1,
1.73 + double amount2, /*@NotNull*/ Currency currency2)
1.74 + throws IllegalArgumentException, CurrencyNotAvailableException {
1.75 + if (amount1 <= 0.0 || amount2 <= 0.0)
1.76 + throw new IllegalArgumentException(
1.77 + String.format("The specified currency values (%1$s, %2$s)", amount1, amount2));
1.78 + return new ConstantRateConverter(currency2, currency1, amount2 / amount1);
1.79 + }
1.80 +
1.81 + /**
1.82 + * Creates a new converter that is able to convert between all specified currencies.
1.83 + *
1.84 + * @param currencies that the converter should be created for
1.85 + *
1.86 + * @return converter able to convert between all specified currencies
1.87 + *
1.88 + * @throws CurrencyNotAvailableException
1.89 + * thrown when one of the currencies is not available
1.90 + */
1.91 + @Override
1.92 + public CurrencyConverter getConverter(/*@NotNull*/ Currency... currencies) throws CurrencyNotAvailableException {
1.93 + for (Currency c : currencies) {
1.94 + if (c == null)
1.95 + throw new NullPointerException("One of the specified currencies is null");
1.96 + if (!rates.containsKey(c))
1.97 + throw new CurrencyNotAvailableException(c);
1.98 + }
1.99 + return new MultiCurrencyConstantRateConverter(rates);
1.100 + }
1.101 +
1.102 + /**
1.103 + * Creates a new converter that is able to convert between all specified currencies.
1.104 + *
1.105 + * @param currencies that the converter should be created for
1.106 + *
1.107 + * @return converter able to convert between all specified currencies
1.108 + *
1.109 + * @throws CurrencyNotAvailableException
1.110 + * thrown when one of the currencies is not available
1.111 + * @throws NullPointerException if any of the specified currencies is null
1.112 + * @throws IllegalArgumentException if any of the specified currencies is not a valid ISO code
1.113 + */
1.114 + @Override
1.115 + public CurrencyConverter getConverter(/*@NotNull*/ String... currencies)
1.116 + throws CurrencyNotAvailableException, IllegalArgumentException, NullPointerException {
1.117 +
1.118 + Currency[] c2 = new Currency[currencies.length];
1.119 + for (int i = 0; i < c2.length; i++)
1.120 + c2[i] = Currency.getInstance(currencies[i]);
1.121 + return getConverter(c2);
1.122 + }
1.123 +}