japod@25: package org.apidesign.apifest08.currency; japod@25: japod@49: import java.util.ArrayList; japod@49: import java.util.Collection; japod@49: import java.util.Collections; japod@49: import java.util.HashSet; japod@49: import java.util.List; japod@49: import java.util.Set; japod@49: japod@25: /** This is the skeleton class for your API. You need to make it public, so japod@25: * it is accessible to your client code (currently in Task1Test.java) file. japod@25: *

japod@25: * Feel free to create additional classes or rename this one, just keep all japod@25: * the API and its implementation in this package. Do not spread it outside japod@25: * to other packages. japod@25: */ japod@25: public final class Convertor { japod@49: //version 1 fields japod@49: japod@49: private String currency1 = null; japod@49: private String currency2 = null; japod@49: private Rate rate = null; japod@49: japod@49: //version 2 field japod@49: private List currencyRates = null; japod@49: japod@49: //version - for compatible mode japod@49: private int instanceVersion = 0; //compatible mode because of problem with empty currency and CZE -> CZE (1:2) rate japod@49: japod@25: Convertor(String currency1, String currency2, Rate rate) { japod@49: instanceVersion = 1; japod@49: if ((currency1 == null) || (currency2 == null) || (rate == null)) { japod@25: throw new IllegalArgumentException("All arguments have to be non-null."); japod@25: } japod@25: this.currency1 = currency1; japod@25: this.currency2 = currency2; japod@25: this.rate = rate; japod@25: } japod@25: japod@49: Convertor(final CurrencyRate ... currencyRate) { japod@49: instanceVersion = 2; japod@49: japod@49: if (currencyRate == null) { japod@49: throw new IllegalArgumentException("Parameter cannot be null."); japod@49: } japod@49: if (currencyRate.length == 0) { japod@49: throw new IllegalArgumentException("CurrencyRates cannot be empty."); japod@49: } japod@49: Set> currencies = new HashSet>(); japod@49: List curRates = new ArrayList(); japod@49: for (int i = 0; i < currencyRate.length; i++) { japod@49: CurrencyRate curRat = currencyRate[i]; japod@49: if (curRat == null) { japod@49: throw new IllegalArgumentException("Parameter cannot be null."); japod@49: } japod@49: //check that currencyRate is not defined twice japod@49: Pair curPair= new Pair(curRat.getCurrency1(), curRat.getCurrency2()); japod@49: if (currencies.contains(curPair)) { japod@49: throw new IllegalArgumentException("Pair of currencies in a currency rate cannot be defined twice"); japod@49: } japod@49: currencies.add(curPair); japod@49: japod@49: curRates.add(curRat); japod@49: } japod@49: this.currencyRates = Collections.unmodifiableList(curRates); japod@49: } japod@49: japod@25: public double convert(String fromCurrency, String toCurrency, int amount) { japod@49: if (instanceVersion == 1) { japod@49: if ((fromCurrency == null) || (toCurrency == null)) { japod@49: throw new IllegalArgumentException("All arguments have to be non-null."); japod@49: } japod@49: japod@49: if (currency1.equals(fromCurrency) && currency2.equals(toCurrency)) { japod@49: return rate.convertAtoB(amount); japod@49: } else if (currency2.equals(fromCurrency) && currency1.equals(toCurrency)) { japod@49: return rate.convertBtoA(amount); japod@49: } else { japod@49: throw new IllegalArgumentException("Convertor " + this.toString() + japod@49: " cannot work with currencies " + fromCurrency + " and " + toCurrency + "."); japod@49: } japod@54: } else { //instanceVersion >= 2 japod@49: //find suitable convertor japod@49: for (CurrencyRate curRate : currencyRates) { japod@49: if ((curRate.getCurrency1().equals(fromCurrency))&& japod@49: (curRate.getCurrency2().equals(toCurrency))) japod@49: { japod@49: return curRate.getRate().convertAtoB(amount); japod@49: } japod@49: } japod@49: //suitable convertor not found, try to find inverse convertor japod@49: for (CurrencyRate curRate : currencyRates) { japod@49: if ((curRate.getCurrency2().equals(fromCurrency))&& japod@49: (curRate.getCurrency1().equals(toCurrency))) japod@49: { japod@49: return curRate.getRate().convertBtoA(amount); japod@49: } japod@49: } japod@49: //even inverse convertor not found japod@49: throw new IllegalArgumentException("Cannot work with selected currencies."); japod@25: } japod@25: } japod@25: japod@25: public double convert(String fromCurrency, String toCurrency, double amount) { japod@49: if (instanceVersion == 1) { japod@49: if ((fromCurrency == null) || (toCurrency == null)) { japod@49: throw new IllegalArgumentException("All arguments have to be non-null."); japod@49: } japod@49: japod@49: if (currency1.equals(fromCurrency) && currency2.equals(toCurrency)) { japod@49: return rate.convertAtoB(amount); japod@49: } else if (currency2.equals(fromCurrency) && currency1.equals(toCurrency)) { japod@49: return rate.convertBtoA(amount); japod@49: } else { japod@49: throw new IllegalArgumentException("Convertor " + this.toString() + japod@49: " cannot work with currencies " + fromCurrency + " and " + toCurrency + "."); japod@49: } japod@54: } else { //instanceVersion >= 2 japod@49: //find suitable convertor japod@49: for (CurrencyRate curRate : currencyRates) { japod@49: if ((curRate.getCurrency1().equals(fromCurrency))&& japod@49: (curRate.getCurrency2().equals(toCurrency))) japod@49: { japod@49: return curRate.getRate().convertAtoB(amount); japod@49: } japod@49: } japod@49: //suitable convertor not found, try to find inverse convertor japod@49: for (CurrencyRate curRate : currencyRates) { japod@49: if ((curRate.getCurrency2().equals(fromCurrency))&& japod@49: (curRate.getCurrency1().equals(toCurrency))) japod@49: { japod@49: return curRate.getRate().convertBtoA(amount); japod@49: } japod@49: } japod@49: //even inverse convertor not found japod@49: throw new IllegalArgumentException("Cannot work with selected currencies."); japod@25: } japod@25: } japod@49: japod@49: /** japod@49: * Returns currency rates. If instantiated with constructor from vesion 1 japod@49: * it creates new collection with one CurrencyRate. japod@49: * Note, it can cause exception because of empty currencies or same currencies. japod@49: */ japod@49: public Collection getCurrencyRates() { japod@49: if (instanceVersion == 1) { japod@49: List ret = new ArrayList(); japod@54: ret.add(new CurrencyRateImpl(currency1, currency2, rate)); //here it checks that currency rate is not nonsense japod@49: return Collections.unmodifiableCollection(ret); japod@54: } else { //instanceVersion >= 2 japod@49: return currencyRates; japod@49: } japod@49: } japod@49: japod@25: @Override japod@25: public String toString() { japod@49: if (instanceVersion == 1) { japod@49: return currency1 + currency2; japod@49: } else { //instanceVersion == 2 japod@49: return super.toString(); //better be compatible in future :-) japod@49: } japod@25: } japod@49: japod@25: @Override japod@25: public boolean equals(Object obj) { japod@49: if (instanceVersion == 1) { japod@49: if (obj == null) { japod@49: return false; japod@49: } japod@49: if (getClass() != obj.getClass()) { japod@49: return false; japod@49: } japod@49: final Convertor other = (Convertor) obj; japod@49: if (this.currency1 != other.currency1 && (this.currency1 == null || !this.currency1.equals(other.currency1))) { japod@49: return false; japod@49: } japod@49: if (this.currency2 != other.currency2 && (this.currency2 == null || !this.currency2.equals(other.currency2))) { japod@49: return false; japod@49: } japod@49: if (this.rate != other.rate && (this.rate == null || !this.rate.equals(other.rate))) { japod@49: return false; japod@49: } japod@49: return true; japod@49: } else { //instanceVersion == 2 japod@49: return super.equals(obj); //better be compatible in future :-) japod@25: } japod@25: } japod@25: japod@25: @Override japod@25: public int hashCode() { japod@49: if (instanceVersion == 1) { japod@49: int hash = 5; japod@49: hash = 67 * hash + (this.currency1 != null ? this.currency1.hashCode() : 0); japod@49: hash = 67 * hash + (this.currency2 != null ? this.currency2.hashCode() : 0); japod@49: hash = 67 * hash + (this.rate != null ? this.rate.hashCode() : 0); japod@25: return hash; japod@49: } else { //instanceVersion == 2 japod@49: return super.hashCode(); //better be compatible in future :-) japod@49: } japod@25: } japod@25: }