task2/solution10/src/org/apidesign/apifest08/currency/OfflineConverterProvider.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Wed, 01 Oct 2008 10:43:05 +0200
changeset 29 f6073056b9fe
parent 6 task1/solution10/src/org/apidesign/apifest08/currency/OfflineConverterProvider.java@97662396c0fd
permissions -rw-r--r--
Getting ready for task2: copying all solutions to new locations
     1 package org.apidesign.apifest08.currency;
     2 
     3 import java.util.*;
     4 
     5 /**
     6  * ConvertorProvider class is introduced to handle
     7  */
     8 public final class OfflineConverterProvider implements CurrencyConverterProvider {
     9 
    10 
    11 	// we can't synchronize on DEFAULT as it's not final and can even be null in synchronized section
    12 	private static final Object LOCK = new Object();
    13 	private static CurrencyConverterProvider DEFAULT;
    14 
    15 	// this is not nice and could be static, but future usage is uncertain and it's pretty easy to create
    16 	private final Map<Currency, Double> rates;
    17 
    18 	private OfflineConverterProvider() {
    19 		rates = new HashMap<Currency, Double>();
    20 		// simple initialization just for Task1Test
    21 		rates.put(Currency.getInstance("USD"), 100.0);
    22 		rates.put(Currency.getInstance("CZK"), 1700.0);
    23 		rates.put(Currency.getInstance("SKK"), 2125.0);
    24 	}
    25 
    26 	/**
    27 	 * Provides default implementation of ConvertorProvider. This Converter does nos not ensure accuracy
    28 	 * of exchange rates, but should be functional at any circumstances including being offline.
    29 	 *
    30 	 * @return
    31 	 */
    32 	public static CurrencyConverterProvider getInstance() {
    33 		// should be necessary in current implementation as creating CurrencyConverterProvider is cheap, but for future
    34 		if (DEFAULT == null)
    35 			synchronized (LOCK) {
    36 				if (DEFAULT == null)
    37 					DEFAULT = new OfflineConverterProvider();
    38 			}
    39 		return DEFAULT;
    40 	}
    41 
    42 	@Override
    43 	public CurrencyConverter getConverter(double amount1, /*@NotNull*/ String currency1,
    44 									   double amount2, /*@NotNull*/ String currency2)
    45 			throws IllegalArgumentException {
    46 
    47 		return getConverter(amount1, Currency.getInstance(currency2), amount2, Currency.getInstance(currency1));
    48 	}
    49 
    50 	/**
    51 	 * Retrieves converter that is capable of converting values between currency1 and currency2. The exchange is
    52 	 * specified in easy to understand way. By specifying values in two currencies that are equal. For example
    53 	 * CurrencyConverter.getConverter(25, "CZK", 1, "EUR"); means 25CKZ is equal to 1EUR. This enables user to
    54 	 * use this method without having to calculate anything. In general this can be expressed by formula
    55 	 * amount1[currency1] = amount2[currency2].
    56 	 *
    57 	 * @param amount1
    58 	 * @param currency1
    59 	 * @param amount2
    60 	 * @param currency2
    61 	 *
    62 	 * @return
    63 	 *
    64 	 * @throws IllegalArgumentException
    65 	 * @throws CurrencyNotAvailableException
    66 	 *
    67 	 */
    68 	@Override
    69 	public CurrencyConverter getConverter(double amount1, /*@NotNull*/ Currency currency1,
    70 									   double amount2, /*@NotNull*/ Currency currency2)
    71 			throws IllegalArgumentException, CurrencyNotAvailableException {
    72 		if (amount1 <= 0.0 || amount2 <= 0.0)
    73 			throw new IllegalArgumentException(
    74 					String.format("The specified currency values (%1$s, %2$s)", amount1, amount2));
    75 		return new ConstantRateConverter(currency2, currency1, amount2 / amount1);
    76 	}
    77 
    78 	/**
    79 	 * Creates a new converter that is able to convert between all specified currencies.
    80 	 *
    81 	 * @param currencies that the converter should be created for
    82 	 *
    83 	 * @return converter able to convert between all specified currencies
    84 	 *
    85 	 * @throws CurrencyNotAvailableException
    86 	 *          thrown when one of the currencies is not available
    87 	 */
    88 	@Override
    89 	public CurrencyConverter getConverter(/*@NotNull*/ Currency... currencies) throws CurrencyNotAvailableException {
    90 		for (Currency c : currencies) {
    91 			if (c == null)
    92 				throw new NullPointerException("One of the specified currencies is null");
    93 			if (!rates.containsKey(c))
    94 				throw new CurrencyNotAvailableException(c);
    95 		}
    96 		return new MultiCurrencyConstantRateConverter(rates);
    97 	}
    98 
    99 	/**
   100 	 * Creates a new converter that is able to convert between all specified currencies.
   101 	 *
   102 	 * @param currencies that the converter should be created for
   103 	 *
   104 	 * @return converter able to convert between all specified currencies
   105 	 *
   106 	 * @throws CurrencyNotAvailableException
   107 	 *                                  thrown when one of the currencies is not available
   108 	 * @throws NullPointerException	 if any of the specified currencies is null
   109 	 * @throws IllegalArgumentException if any of the specified currencies is not a valid ISO code
   110 	 */
   111 	@Override
   112 	public CurrencyConverter getConverter(/*@NotNull*/ String... currencies)
   113 			throws CurrencyNotAvailableException, IllegalArgumentException, NullPointerException {
   114 
   115 		Currency[] c2 = new Currency[currencies.length];
   116 		for (int i = 0; i < c2.length; i++)
   117 			c2[i] = Currency.getInstance(currencies[i]);
   118 		return getConverter(c2);
   119 	}
   120 }