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: }