1 package org.apidesign.apifest08.currency;
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.Collections;
7 import java.util.HashSet;
11 /** This is the skeleton class for your API. You need to make it public, so
12 * it is accessible to your client code (currently in Task1Test.java) file.
14 * Feel free to create additional classes or rename this one, just keep all
15 * the API and its implementation in this package. Do not spread it outside
18 public final class Convertor {
21 private String currency1 = null;
22 private String currency2 = null;
23 private Rate rate = null;
26 private List<TimeLimitedCurrencyRate> currencyRates = null;
28 //version - for compatible mode
29 private int instanceVersion = 0; //compatible mode because of problem with empty currency and CZE -> CZE (1:2) rate
31 Convertor(String currency1, String currency2, Rate rate) {
33 if ((currency1 == null) || (currency2 == null) || (rate == null)) {
34 throw new IllegalArgumentException("All arguments have to be non-null.");
36 this.currency1 = currency1;
37 this.currency2 = currency2;
41 Convertor(final CurrencyRate ... currencyRate) {
44 if (currencyRate == null) {
45 throw new IllegalArgumentException("Parameter cannot be null.");
47 if (currencyRate.length == 0) {
48 throw new IllegalArgumentException("CurrencyRates cannot be empty.");
50 Set<Pair<String,String>> currencies = new HashSet<Pair<String,String>>();
51 List<TimeLimitedCurrencyRate> curRates = new ArrayList<TimeLimitedCurrencyRate>();
52 for (int i = 0; i < currencyRate.length; i++) {
53 final CurrencyRate curRat = currencyRate[i];
55 throw new IllegalArgumentException("Parameter cannot be null.");
57 //check that currencyRate is not defined twice
58 Pair<String, String> curPair= new Pair<String, String>(curRat.getCurrency1(), curRat.getCurrency2());
59 if (currencies.contains(curPair)) {
60 throw new IllegalArgumentException("Pair of currencies in a currency rate cannot be defined twice");
62 currencies.add(curPair);
64 if (curRat instanceof TimeLimitedCurrencyRate) {
65 curRates.add((TimeLimitedCurrencyRate)curRat);
67 curRates.add(new TimeLimitedCurrencyRate() { //create delegate which implements TimeLimitedCurrencyRate
68 public long getFromTime() {
69 return Long.MIN_VALUE;
72 public long getToTime() {
73 return Long.MAX_VALUE;
76 public String getCurrency1() {
77 return curRat.getCurrency1();
80 public String getCurrency2() {
81 return curRat.getCurrency2();
84 public Rate getRate() {
85 return curRat.getRate();
90 this.currencyRates = Collections.unmodifiableList(curRates);
93 Convertor(final int fakeParameter, final TimeLimitedCurrencyRate ... currencyRate) { //use fake parameter just to specify which constructor should be invoked
96 if (currencyRate == null) {
97 throw new IllegalArgumentException("Parameter cannot be null.");
99 List<TimeLimitedCurrencyRate> curRates = new ArrayList<TimeLimitedCurrencyRate>();
100 for (int i = 0; i < currencyRate.length; i++) {
101 final TimeLimitedCurrencyRate curRat = currencyRate[i];
102 if (curRat == null) {
103 throw new IllegalArgumentException("Parameter cannot be null.");
106 curRates.add(curRat);
108 this.currencyRates = Collections.unmodifiableList(curRates);
111 public double convert(String fromCurrency, String toCurrency, int amount) {
112 return convert(fromCurrency, toCurrency, amount, System.currentTimeMillis());
115 public double convert(String fromCurrency, String toCurrency, int amount, Date date) {
117 throw new IllegalArgumentException("Date cannot be null");
119 return convert(fromCurrency, toCurrency, amount, date.getTime());
122 public double convert(String fromCurrency, String toCurrency, int amount, long time) {
123 if (instanceVersion == 1) {
124 if ((fromCurrency == null) || (toCurrency == null)) {
125 throw new IllegalArgumentException("All arguments have to be non-null.");
128 if (currency1.equals(fromCurrency) && currency2.equals(toCurrency)) {
129 return rate.convertAtoB(amount);
130 } else if (currency2.equals(fromCurrency) && currency1.equals(toCurrency)) {
131 return rate.convertBtoA(amount);
133 throw new IllegalArgumentException("Convertor " + this.toString() +
134 " cannot work with currencies " + fromCurrency + " and " + toCurrency + ".");
136 } else { //instanceVersion >= 2
137 //find suitable convertor
138 for (TimeLimitedCurrencyRate curRate : currencyRates) {
139 if ((curRate.getCurrency1().equals(fromCurrency))&&
140 (curRate.getCurrency2().equals(toCurrency))&&
141 (curRate.getFromTime() <= time) &&
142 (curRate.getToTime() >= time))
144 return curRate.getRate().convertAtoB(amount);
147 //suitable convertor not found, try to find inverse convertor
148 for (TimeLimitedCurrencyRate curRate : currencyRates) {
149 if ((curRate.getCurrency2().equals(fromCurrency))&&
150 (curRate.getCurrency1().equals(toCurrency))&&
151 (curRate.getFromTime() <= time) &&
152 (curRate.getToTime() >= time))
154 return curRate.getRate().convertBtoA(amount);
157 //even inverse convertor not found
158 throw new IllegalArgumentException("Cannot work with selected currencies.");
162 public double convert(String fromCurrency, String toCurrency, double amount) {
163 return convert(fromCurrency, toCurrency, amount, System.currentTimeMillis());
166 public double convert(String fromCurrency, String toCurrency, double amount, Date date) {
168 throw new IllegalArgumentException("Date cannot be null");
170 return convert(fromCurrency, toCurrency, amount, date.getTime());
173 public double convert(String fromCurrency, String toCurrency, double amount, long time) {
174 if (instanceVersion == 1) {
175 if ((fromCurrency == null) || (toCurrency == null)) {
176 throw new IllegalArgumentException("All arguments have to be non-null.");
179 if (currency1.equals(fromCurrency) && currency2.equals(toCurrency)) {
180 return rate.convertAtoB(amount);
181 } else if (currency2.equals(fromCurrency) && currency1.equals(toCurrency)) {
182 return rate.convertBtoA(amount);
184 throw new IllegalArgumentException("Convertor " + this.toString() +
185 " cannot work with currencies " + fromCurrency + " and " + toCurrency + ".");
187 } else { //instanceVersion >= 2
188 //find suitable convertor
189 for (TimeLimitedCurrencyRate curRate : currencyRates) {
190 if ((curRate.getCurrency1().equals(fromCurrency))&&
191 (curRate.getCurrency2().equals(toCurrency))&&
192 (curRate.getFromTime() <= time) &&
193 (curRate.getToTime() >= time))
195 return curRate.getRate().convertAtoB(amount);
198 //suitable convertor not found, try to find inverse convertor
199 for (TimeLimitedCurrencyRate curRate : currencyRates) {
200 if ((curRate.getCurrency2().equals(fromCurrency))&&
201 (curRate.getCurrency1().equals(toCurrency))&&
202 (curRate.getFromTime() <= time) &&
203 (curRate.getToTime() >= time))
205 return curRate.getRate().convertBtoA(amount);
208 //even inverse convertor not found
209 throw new IllegalArgumentException("Cannot work with selected currencies.");
214 * Returns currency rates. If instantiated with constructor from vesion 1
215 * it creates new collection with one CurrencyRate.
216 * Note, it can cause exception because of empty currencies or same currencies.
218 public Collection<CurrencyRate> getCurrencyRates() {
219 if (instanceVersion == 1) {
220 List<CurrencyRate> ret = new ArrayList<CurrencyRate>();
221 ret.add(new CurrencyRateImpl(currency1, currency2, rate)); //here it checks that currency rate is not nonsense
222 return Collections.unmodifiableCollection(ret);
223 } else { //instanceVersion >= 2
224 List<CurrencyRate> ret = new ArrayList<CurrencyRate>(currencyRates);
225 return Collections.unmodifiableCollection(ret);
229 public Collection<TimeLimitedCurrencyRate> getTimeLimitedCurrencyRates() {
230 if (instanceVersion == 1) {
231 List<TimeLimitedCurrencyRate> ret = new ArrayList<TimeLimitedCurrencyRate>();
232 ret.add(new CurrencyRateImpl(currency1, currency2, rate)); //here it checks that currency rate is not nonsense
233 return Collections.unmodifiableCollection(ret);
234 } else { //instanceVersion >= 2
235 List<TimeLimitedCurrencyRate> ret = new ArrayList<TimeLimitedCurrencyRate>(currencyRates);
236 return Collections.unmodifiableCollection(ret);
241 public String toString() {
242 if (instanceVersion == 1) {
243 return currency1 + currency2;
244 } else { //instanceVersion == 2
245 return super.toString(); //better be compatible in future :-)
250 public boolean equals(Object obj) {
251 if (instanceVersion == 1) {
255 if (getClass() != obj.getClass()) {
258 final Convertor other = (Convertor) obj;
259 if (this.currency1 != other.currency1 && (this.currency1 == null || !this.currency1.equals(other.currency1))) {
262 if (this.currency2 != other.currency2 && (this.currency2 == null || !this.currency2.equals(other.currency2))) {
265 if (this.rate != other.rate && (this.rate == null || !this.rate.equals(other.rate))) {
269 } else { //instanceVersion == 2
270 return super.equals(obj); //better be compatible in future :-)
275 public int hashCode() {
276 if (instanceVersion == 1) {
278 hash = 67 * hash + (this.currency1 != null ? this.currency1.hashCode() : 0);
279 hash = 67 * hash + (this.currency2 != null ? this.currency2.hashCode() : 0);
280 hash = 67 * hash + (this.rate != null ? this.rate.hashCode() : 0);
282 } else { //instanceVersion == 2
283 return super.hashCode(); //better be compatible in future :-)