japod@25
|
1 |
package org.apidesign.apifest08.currency;
|
japod@25
|
2 |
|
japod@49
|
3 |
import java.util.ArrayList;
|
japod@49
|
4 |
import java.util.Collection;
|
japod@49
|
5 |
import java.util.Collections;
|
japod@49
|
6 |
import java.util.HashSet;
|
japod@49
|
7 |
import java.util.List;
|
japod@49
|
8 |
import java.util.Set;
|
japod@49
|
9 |
|
japod@25
|
10 |
/** This is the skeleton class for your API. You need to make it public, so
|
japod@25
|
11 |
* it is accessible to your client code (currently in Task1Test.java) file.
|
japod@25
|
12 |
* <p>
|
japod@25
|
13 |
* Feel free to create additional classes or rename this one, just keep all
|
japod@25
|
14 |
* the API and its implementation in this package. Do not spread it outside
|
japod@25
|
15 |
* to other packages.
|
japod@25
|
16 |
*/
|
japod@25
|
17 |
public final class Convertor {
|
japod@49
|
18 |
//version 1 fields
|
japod@49
|
19 |
|
japod@49
|
20 |
private String currency1 = null;
|
japod@49
|
21 |
private String currency2 = null;
|
japod@49
|
22 |
private Rate rate = null;
|
japod@49
|
23 |
|
japod@49
|
24 |
//version 2 field
|
japod@49
|
25 |
private List<CurrencyRate> currencyRates = null;
|
japod@49
|
26 |
|
japod@49
|
27 |
//version - for compatible mode
|
japod@49
|
28 |
private int instanceVersion = 0; //compatible mode because of problem with empty currency and CZE -> CZE (1:2) rate
|
japod@49
|
29 |
|
japod@25
|
30 |
Convertor(String currency1, String currency2, Rate rate) {
|
japod@49
|
31 |
instanceVersion = 1;
|
japod@49
|
32 |
if ((currency1 == null) || (currency2 == null) || (rate == null)) {
|
japod@25
|
33 |
throw new IllegalArgumentException("All arguments have to be non-null.");
|
japod@25
|
34 |
}
|
japod@25
|
35 |
this.currency1 = currency1;
|
japod@25
|
36 |
this.currency2 = currency2;
|
japod@25
|
37 |
this.rate = rate;
|
japod@25
|
38 |
}
|
japod@25
|
39 |
|
japod@49
|
40 |
Convertor(final CurrencyRate ... currencyRate) {
|
japod@49
|
41 |
instanceVersion = 2;
|
japod@49
|
42 |
|
japod@49
|
43 |
if (currencyRate == null) {
|
japod@49
|
44 |
throw new IllegalArgumentException("Parameter cannot be null.");
|
japod@49
|
45 |
}
|
japod@49
|
46 |
if (currencyRate.length == 0) {
|
japod@49
|
47 |
throw new IllegalArgumentException("CurrencyRates cannot be empty.");
|
japod@49
|
48 |
}
|
japod@49
|
49 |
Set<Pair<String,String>> currencies = new HashSet<Pair<String,String>>();
|
japod@49
|
50 |
List<CurrencyRate> curRates = new ArrayList<CurrencyRate>();
|
japod@49
|
51 |
for (int i = 0; i < currencyRate.length; i++) {
|
japod@49
|
52 |
CurrencyRate curRat = currencyRate[i];
|
japod@49
|
53 |
if (curRat == null) {
|
japod@49
|
54 |
throw new IllegalArgumentException("Parameter cannot be null.");
|
japod@49
|
55 |
}
|
japod@49
|
56 |
//check that currencyRate is not defined twice
|
japod@49
|
57 |
Pair<String, String> curPair= new Pair<String, String>(curRat.getCurrency1(), curRat.getCurrency2());
|
japod@49
|
58 |
if (currencies.contains(curPair)) {
|
japod@49
|
59 |
throw new IllegalArgumentException("Pair of currencies in a currency rate cannot be defined twice");
|
japod@49
|
60 |
}
|
japod@49
|
61 |
currencies.add(curPair);
|
japod@49
|
62 |
|
japod@49
|
63 |
curRates.add(curRat);
|
japod@49
|
64 |
}
|
japod@49
|
65 |
this.currencyRates = Collections.unmodifiableList(curRates);
|
japod@49
|
66 |
}
|
japod@49
|
67 |
|
japod@25
|
68 |
public double convert(String fromCurrency, String toCurrency, int amount) {
|
japod@49
|
69 |
if (instanceVersion == 1) {
|
japod@49
|
70 |
if ((fromCurrency == null) || (toCurrency == null)) {
|
japod@49
|
71 |
throw new IllegalArgumentException("All arguments have to be non-null.");
|
japod@49
|
72 |
}
|
japod@49
|
73 |
|
japod@49
|
74 |
if (currency1.equals(fromCurrency) && currency2.equals(toCurrency)) {
|
japod@49
|
75 |
return rate.convertAtoB(amount);
|
japod@49
|
76 |
} else if (currency2.equals(fromCurrency) && currency1.equals(toCurrency)) {
|
japod@49
|
77 |
return rate.convertBtoA(amount);
|
japod@49
|
78 |
} else {
|
japod@49
|
79 |
throw new IllegalArgumentException("Convertor " + this.toString() +
|
japod@49
|
80 |
" cannot work with currencies " + fromCurrency + " and " + toCurrency + ".");
|
japod@49
|
81 |
}
|
japod@54
|
82 |
} else { //instanceVersion >= 2
|
japod@49
|
83 |
//find suitable convertor
|
japod@49
|
84 |
for (CurrencyRate curRate : currencyRates) {
|
japod@49
|
85 |
if ((curRate.getCurrency1().equals(fromCurrency))&&
|
japod@49
|
86 |
(curRate.getCurrency2().equals(toCurrency)))
|
japod@49
|
87 |
{
|
japod@49
|
88 |
return curRate.getRate().convertAtoB(amount);
|
japod@49
|
89 |
}
|
japod@49
|
90 |
}
|
japod@49
|
91 |
//suitable convertor not found, try to find inverse convertor
|
japod@49
|
92 |
for (CurrencyRate curRate : currencyRates) {
|
japod@49
|
93 |
if ((curRate.getCurrency2().equals(fromCurrency))&&
|
japod@49
|
94 |
(curRate.getCurrency1().equals(toCurrency)))
|
japod@49
|
95 |
{
|
japod@49
|
96 |
return curRate.getRate().convertBtoA(amount);
|
japod@49
|
97 |
}
|
japod@49
|
98 |
}
|
japod@49
|
99 |
//even inverse convertor not found
|
japod@49
|
100 |
throw new IllegalArgumentException("Cannot work with selected currencies.");
|
japod@25
|
101 |
}
|
japod@25
|
102 |
}
|
japod@25
|
103 |
|
japod@25
|
104 |
public double convert(String fromCurrency, String toCurrency, double amount) {
|
japod@49
|
105 |
if (instanceVersion == 1) {
|
japod@49
|
106 |
if ((fromCurrency == null) || (toCurrency == null)) {
|
japod@49
|
107 |
throw new IllegalArgumentException("All arguments have to be non-null.");
|
japod@49
|
108 |
}
|
japod@49
|
109 |
|
japod@49
|
110 |
if (currency1.equals(fromCurrency) && currency2.equals(toCurrency)) {
|
japod@49
|
111 |
return rate.convertAtoB(amount);
|
japod@49
|
112 |
} else if (currency2.equals(fromCurrency) && currency1.equals(toCurrency)) {
|
japod@49
|
113 |
return rate.convertBtoA(amount);
|
japod@49
|
114 |
} else {
|
japod@49
|
115 |
throw new IllegalArgumentException("Convertor " + this.toString() +
|
japod@49
|
116 |
" cannot work with currencies " + fromCurrency + " and " + toCurrency + ".");
|
japod@49
|
117 |
}
|
japod@54
|
118 |
} else { //instanceVersion >= 2
|
japod@49
|
119 |
//find suitable convertor
|
japod@49
|
120 |
for (CurrencyRate curRate : currencyRates) {
|
japod@49
|
121 |
if ((curRate.getCurrency1().equals(fromCurrency))&&
|
japod@49
|
122 |
(curRate.getCurrency2().equals(toCurrency)))
|
japod@49
|
123 |
{
|
japod@49
|
124 |
return curRate.getRate().convertAtoB(amount);
|
japod@49
|
125 |
}
|
japod@49
|
126 |
}
|
japod@49
|
127 |
//suitable convertor not found, try to find inverse convertor
|
japod@49
|
128 |
for (CurrencyRate curRate : currencyRates) {
|
japod@49
|
129 |
if ((curRate.getCurrency2().equals(fromCurrency))&&
|
japod@49
|
130 |
(curRate.getCurrency1().equals(toCurrency)))
|
japod@49
|
131 |
{
|
japod@49
|
132 |
return curRate.getRate().convertBtoA(amount);
|
japod@49
|
133 |
}
|
japod@49
|
134 |
}
|
japod@49
|
135 |
//even inverse convertor not found
|
japod@49
|
136 |
throw new IllegalArgumentException("Cannot work with selected currencies.");
|
japod@25
|
137 |
}
|
japod@25
|
138 |
}
|
japod@49
|
139 |
|
japod@49
|
140 |
/**
|
japod@49
|
141 |
* Returns currency rates. If instantiated with constructor from vesion 1
|
japod@49
|
142 |
* it creates new collection with one CurrencyRate.
|
japod@49
|
143 |
* Note, it can cause exception because of empty currencies or same currencies.
|
japod@49
|
144 |
*/
|
japod@49
|
145 |
public Collection<CurrencyRate> getCurrencyRates() {
|
japod@49
|
146 |
if (instanceVersion == 1) {
|
japod@49
|
147 |
List<CurrencyRate> ret = new ArrayList<CurrencyRate>();
|
japod@54
|
148 |
ret.add(new CurrencyRateImpl(currency1, currency2, rate)); //here it checks that currency rate is not nonsense
|
japod@49
|
149 |
return Collections.unmodifiableCollection(ret);
|
japod@54
|
150 |
} else { //instanceVersion >= 2
|
japod@49
|
151 |
return currencyRates;
|
japod@49
|
152 |
}
|
japod@49
|
153 |
}
|
japod@49
|
154 |
|
japod@25
|
155 |
@Override
|
japod@25
|
156 |
public String toString() {
|
japod@49
|
157 |
if (instanceVersion == 1) {
|
japod@49
|
158 |
return currency1 + currency2;
|
japod@49
|
159 |
} else { //instanceVersion == 2
|
japod@49
|
160 |
return super.toString(); //better be compatible in future :-)
|
japod@49
|
161 |
}
|
japod@25
|
162 |
}
|
japod@49
|
163 |
|
japod@25
|
164 |
@Override
|
japod@25
|
165 |
public boolean equals(Object obj) {
|
japod@49
|
166 |
if (instanceVersion == 1) {
|
japod@49
|
167 |
if (obj == null) {
|
japod@49
|
168 |
return false;
|
japod@49
|
169 |
}
|
japod@49
|
170 |
if (getClass() != obj.getClass()) {
|
japod@49
|
171 |
return false;
|
japod@49
|
172 |
}
|
japod@49
|
173 |
final Convertor other = (Convertor) obj;
|
japod@49
|
174 |
if (this.currency1 != other.currency1 && (this.currency1 == null || !this.currency1.equals(other.currency1))) {
|
japod@49
|
175 |
return false;
|
japod@49
|
176 |
}
|
japod@49
|
177 |
if (this.currency2 != other.currency2 && (this.currency2 == null || !this.currency2.equals(other.currency2))) {
|
japod@49
|
178 |
return false;
|
japod@49
|
179 |
}
|
japod@49
|
180 |
if (this.rate != other.rate && (this.rate == null || !this.rate.equals(other.rate))) {
|
japod@49
|
181 |
return false;
|
japod@49
|
182 |
}
|
japod@49
|
183 |
return true;
|
japod@49
|
184 |
} else { //instanceVersion == 2
|
japod@49
|
185 |
return super.equals(obj); //better be compatible in future :-)
|
japod@25
|
186 |
}
|
japod@25
|
187 |
}
|
japod@25
|
188 |
|
japod@25
|
189 |
@Override
|
japod@25
|
190 |
public int hashCode() {
|
japod@49
|
191 |
if (instanceVersion == 1) {
|
japod@49
|
192 |
int hash = 5;
|
japod@49
|
193 |
hash = 67 * hash + (this.currency1 != null ? this.currency1.hashCode() : 0);
|
japod@49
|
194 |
hash = 67 * hash + (this.currency2 != null ? this.currency2.hashCode() : 0);
|
japod@49
|
195 |
hash = 67 * hash + (this.rate != null ? this.rate.hashCode() : 0);
|
japod@25
|
196 |
return hash;
|
japod@49
|
197 |
} else { //instanceVersion == 2
|
japod@49
|
198 |
return super.hashCode(); //better be compatible in future :-)
|
japod@49
|
199 |
}
|
japod@25
|
200 |
}
|
japod@25
|
201 |
}
|