task4/solution04/src/org/apidesign/apifest08/currency/ExchangeRate.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 
     4 import java.math.BigDecimal;
     5 import java.math.RoundingMode;
     6 import java.util.Collections;
     7 import java.util.Currency;
     8 import java.util.HashSet;
     9 import java.util.Set;
    10 
    11 
    12 /**
    13  * The exchange rate between two currencies.
    14  *
    15  * @author D'Arcy Smith
    16  * @version 1.1
    17  */
    18 public final class ExchangeRate
    19 {
    20     /**
    21      * 
    22      */
    23     private final Currency currencyA;
    24 
    25     /**
    26      * 
    27      */
    28     private final Currency currencyB;
    29 
    30     /**
    31      * 
    32      */
    33     private final BigDecimal rateAtoB;
    34 
    35     /**
    36      * 
    37      */
    38     private final BigDecimal rateBtoA;
    39 
    40     /**
    41      * Construct an ExchangeRate with the specified values.
    42      * 
    43      * @param a the first currency
    44      * @param b the second currency
    45      * @param ra the rate to convert a to b
    46      * @param rb the rate to covertt b to a
    47      * @throws IllegalArgumentException if any parameter is null.
    48      */
    49     public ExchangeRate(final Currency   a,
    50                         final Currency   b,
    51                         final BigDecimal ra,
    52                         final BigDecimal rb)
    53     {
    54         if(a == null)
    55         {
    56             throw new IllegalArgumentException("a cannot be null");
    57         }
    58         
    59         if(b == null)
    60         {
    61             throw new IllegalArgumentException("b cannot be null");
    62         }
    63         
    64         if(ra == null)
    65         {
    66             throw new IllegalArgumentException("ra cannot be null");
    67         }
    68         
    69         if(rb == null)
    70         {
    71             throw new IllegalArgumentException("rb cannot be null");
    72         }
    73         
    74         if(ra.compareTo(BigDecimal.ZERO) <= 0)
    75         {
    76             throw new IllegalArgumentException("ra cannot be <= 0, was: " + ra);
    77         }
    78         
    79         if(rb.compareTo(BigDecimal.ZERO) <= 0)
    80         {
    81             throw new IllegalArgumentException("rb cannot be <= 0, was: " + ra);
    82         }
    83         
    84         currencyA = a;
    85         currencyB = b;
    86         rateAtoB  = ra;
    87         rateBtoA  = rb;
    88     }
    89 
    90     /**
    91      * Get the first currency.
    92      * 
    93      * @return the first currency.
    94      */
    95     public Currency getCurrencyA()
    96     {
    97         return currencyA;
    98     }
    99 
   100     /**
   101      * Get the second currency.
   102      * 
   103      * @return the second currency.
   104      */
   105     public Currency getCurrencyB()
   106     {
   107         return currencyB;
   108     }
   109 
   110     /**
   111      * Get the conversion rate from currencyA to currencyB.
   112      * 
   113      * @return the conversion rate from currencyA to currencyB.
   114      */
   115     public BigDecimal getRateAtoB()
   116     {
   117         return rateAtoB;
   118     }
   119 
   120     /**
   121      * Get the conversion rate from currencyB to currencyA.
   122      * 
   123      * @return the conversion rate from currencyB to currencyA.
   124      */
   125     public BigDecimal getRateBtoA()
   126     {
   127         return rateBtoA;
   128     }
   129     
   130     public static ExchangeRate getExchangeRate(final Currency   a,
   131                                                final Currency   b,
   132                                                final BigDecimal va,
   133                                                final BigDecimal vb)
   134     {
   135         final BigDecimal   rateAtoB;
   136         final BigDecimal   rateBtoA;
   137         final ExchangeRate rate;    
   138         
   139         if(a == null)
   140         {
   141             throw new IllegalArgumentException("a cannot be null");
   142         }
   143         
   144         if(b == null)
   145         {
   146             throw new IllegalArgumentException("b cannot be null");
   147         }
   148 
   149         if(a.equals(b))
   150         {
   151             rateAtoB = BigDecimal.ONE;
   152             rateBtoA = BigDecimal.ONE;
   153         }
   154         else 
   155         {
   156             rateAtoB = vb.divide(va, 20, RoundingMode.HALF_DOWN);
   157             rateBtoA = va.divide(vb, 20, RoundingMode.HALF_DOWN);
   158         }
   159         
   160         rate = new ExchangeRate(a, 
   161                                 b,
   162                                 rateAtoB.setScale(20, RoundingMode.HALF_EVEN),
   163                                 rateBtoA.setScale(20, RoundingMode.HALF_EVEN));
   164         
   165         return (rate);
   166     }
   167 
   168     public BigDecimal convert(final Currency   from,
   169                               final Currency   to,
   170                               final BigDecimal amount)
   171         throws InvalidConversionException
   172     {
   173         final BigDecimal result;
   174         
   175         if(amount == null)
   176         {
   177             throw new IllegalArgumentException("amount cannot be null");
   178         }
   179         
   180         if(from == null)
   181         {
   182             throw new IllegalArgumentException("from cannot be null");
   183         }
   184         
   185         if(to == null)
   186         {
   187             throw new IllegalArgumentException("to cannot be null");
   188         }
   189         
   190         if(!(from.equals(currencyA)) && (!(from.equals(currencyB))))
   191         {
   192             throw new InvalidConversionException("cannot convert from: " + from.getCurrencyCode(), from, currencyA, currencyB);
   193         }
   194         
   195         if(!(to.equals(currencyA)) && (!(to.equals(currencyB))))
   196         {
   197             throw new InvalidConversionException("cannot convert to: " + to.getCurrencyCode(), to, currencyA, currencyB);
   198         }
   199 
   200         result = amount.multiply(getConversionRate(from, to));
   201 
   202         return (result.setScale(2, RoundingMode.HALF_DOWN));
   203     }
   204     
   205     /**
   206      * Check to see if converting between the two currencies is possible.
   207      * 
   208      * @param from the currency to convert from.
   209      * @param to the currency to convert to.
   210      * @return true if the conversion is possible.
   211      * @throws IllegalArgumentException if either from or to are null.
   212      */
   213     public boolean canConvert(final Currency from, final Currency to)
   214     {
   215         if(from == null)
   216         {
   217             throw new IllegalArgumentException("from cannot be null");
   218         }
   219         
   220         if(to == null)
   221         {
   222             throw new IllegalArgumentException("to cannot be null");
   223         }
   224         
   225         return ((from.equals(currencyA) || from.equals(currencyB)) &&
   226                 (to.equals(currencyA)   || to.equals(currencyB)));
   227     }
   228     /**
   229      * Get the currencies that the convertor supports.
   230      * 
   231      * @return the supported currencies.
   232      */
   233     public Set<Currency> getCurrencies()
   234     {
   235         final Set<Currency> currencies;
   236         
   237         currencies = new HashSet<Currency>();
   238         currencies.add(currencyA);
   239         currencies.add(currencyB);
   240 
   241         return (Collections.unmodifiableSet(currencies));
   242     }
   243 
   244     /**
   245      * Get the conversion rate between two currencies.
   246      * 
   247      * @param from the currency to convert from.
   248      * @param to the currency to convert to.
   249      * @return the conversion rate between the two currencies.
   250      * @throws InvalidConversionException if canConvert would return false.
   251      * @throws IllegalArgumentException if either from or to are null.
   252      */
   253     public BigDecimal getConversionRate(final Currency from, 
   254                                         final Currency to)
   255         throws InvalidConversionException
   256     {                
   257         final BigDecimal rate;
   258         
   259         if(from == null)
   260         {
   261             throw new IllegalArgumentException("from cannot be null");
   262         }
   263         
   264         if(to == null)
   265         {
   266             throw new IllegalArgumentException("to cannot be null");
   267         }
   268 
   269         if(from.equals(to))
   270         {
   271             rate = BigDecimal.ONE;
   272         }
   273         else 
   274         {
   275             if(from.equals(currencyA))
   276             {
   277                 rate = rateAtoB;
   278             }
   279             else
   280             {
   281                 rate = rateBtoA;
   282             }
   283         }
   284         
   285         return (rate);
   286     }
   287 
   288     public String toString()
   289     {
   290         return (rateAtoB + " : " + rateBtoA);
   291     }
   292 
   293     @Override
   294     public boolean equals(Object obj) {
   295         if (obj == null) {
   296             return false;
   297         }
   298         if (getClass() != obj.getClass()) {
   299             return false;
   300         }
   301         final ExchangeRate other = (ExchangeRate) obj;
   302         if (this.currencyA != other.currencyA && (this.currencyA == null || !this.currencyA.equals(other.currencyA))) {
   303             return false;
   304         }
   305         if (this.currencyB != other.currencyB && (this.currencyB == null || !this.currencyB.equals(other.currencyB))) {
   306             return false;
   307         }
   308         if (this.rateAtoB != other.rateAtoB && (this.rateAtoB == null || !this.rateAtoB.equals(other.rateAtoB))) {
   309             return false;
   310         }
   311         if (this.rateBtoA != other.rateBtoA && (this.rateBtoA == null || !this.rateBtoA.equals(other.rateBtoA))) {
   312             return false;
   313         }
   314         return true;
   315     }
   316 
   317     @Override
   318     public int hashCode() {
   319         int hash = 7;
   320         hash = 97 * hash + (this.currencyA != null ? this.currencyA.hashCode() : 0);
   321         hash = 97 * hash + (this.currencyB != null ? this.currencyB.hashCode() : 0);
   322         hash = 97 * hash + (this.rateAtoB != null ? this.rateAtoB.hashCode() : 0);
   323         hash = 97 * hash + (this.rateBtoA != null ? this.rateBtoA.hashCode() : 0);
   324         return hash;
   325     }
   326 }