1 package org.apidesign.apifest08.currency;
3 import java.io.Serializable;
4 import java.math.BigDecimal;
5 import java.math.RoundingMode;
6 import java.util.Currency;
9 * Default {@link Convertor} implementation. Exchange rate is stored as equivalents. It means if we have USD to CZK convertor and USD1 = CZK17
10 * we store 1 in sourceEquivalent and 17 in destinationEquivalent. This class is immutable.
14 class DefaultConvertor implements Convertor, Serializable {
16 private static final long serialVersionUID = -1754789142402148099L;
19 * Equivalent in source currency.
21 private final BigDecimal sourceEquivalent;
24 * Equivalent in destination currency.
26 private final BigDecimal destinationEquivalent;
28 private final Currency sourceCurrency;
30 private final Currency destinationCurrency;
32 public DefaultConvertor(BigDecimal sourceEquivalent, BigDecimal destinationEquivalent, Currency sourceCurrency, Currency destinationCurrency) {
34 if (BigDecimal.ZERO.compareTo(sourceEquivalent)==0)
36 throw new IllegalArgumentException("Source equivalent amount can not be 0.");
38 if (BigDecimal.ZERO.compareTo(destinationEquivalent)==0)
40 throw new IllegalArgumentException("Destination equivalent amount can not be 0.");
42 this.sourceEquivalent = sourceEquivalent;
43 this.destinationEquivalent = destinationEquivalent;
44 this.sourceCurrency = sourceCurrency;
45 this.destinationCurrency = destinationCurrency;
48 public Money convert(Money amount, Currency destinationCurrency) {
51 throw new NullPointerException("Money is null");
53 if (destinationCurrency==null)
55 throw new NullPointerException("destionationCurrency is null");
57 if (isConversionInOpositeDirection(amount, destinationCurrency))
59 return revert().convert(amount, destinationCurrency);
61 if (!amount.getCurrency().equals(getSourceCurrency()))
63 throw new IllegalArgumentException("Can not convert from "+amount.getCurrency()+". Converts between "+getSourceCurrency()+" and "+getDestinationCurrency());
65 if (!getDestinationCurrency().equals(destinationCurrency))
67 throw new IllegalArgumentException("Can not convert to "+destinationCurrency+". Converts between "+getSourceCurrency()+" and "+getDestinationCurrency());
69 BigDecimal sourceAmount = amount.getAmount();
70 BigDecimal destinationAmount = sourceAmount.multiply(destinationEquivalent).divide(sourceEquivalent, 2, RoundingMode.HALF_UP);
71 return new MoneyImpl(destinationAmount, getDestinationCurrency());
75 * Returns true, if the conversion is in oposit direction.
77 * @param destinationCurrency
80 private boolean isConversionInOpositeDirection(Money amount, Currency destinationCurrency) {
81 return amount.getCurrency().equals(getDestinationCurrency()) && destinationCurrency.equals(getSourceCurrency());
85 public Convertor revert() {
86 return new DefaultConvertor(destinationEquivalent, sourceEquivalent, destinationCurrency, sourceCurrency);
89 public BigDecimal getSourceEquivalent() {
90 return sourceEquivalent;
93 public BigDecimal getDestinationEquivalent() {
94 return destinationEquivalent;
97 public Currency getSourceCurrency() {
98 return sourceCurrency;
101 public Currency getDestinationCurrency() {
102 return destinationCurrency;
106 public String toString() {
107 return getClass().getName()+" converts "+getSourceCurrency()+" to "+getDestinationCurrency()+" "
108 +getSourceCurrency()+getSourceEquivalent()+"="+getDestinationCurrency()+getDestinationEquivalent();
112 public int hashCode() {
113 final int prime = 31;
117 + ((destinationCurrency == null) ? 0 : destinationCurrency
121 + ((destinationEquivalent == null) ? 0 : destinationEquivalent
123 result = prime * result
124 + ((sourceCurrency == null) ? 0 : sourceCurrency.hashCode());
127 + ((sourceEquivalent == null) ? 0 : sourceEquivalent.hashCode());
132 public boolean equals(Object obj) {
137 if (!(obj instanceof DefaultConvertor))
139 DefaultConvertor other = (DefaultConvertor) obj;
140 if (destinationCurrency == null) {
141 if (other.destinationCurrency != null)
143 } else if (!destinationCurrency.equals(other.destinationCurrency))
145 if (destinationEquivalent == null) {
146 if (other.destinationEquivalent != null)
148 } else if (!destinationEquivalent.equals(other.destinationEquivalent))
150 if (sourceCurrency == null) {
151 if (other.sourceCurrency != null)
153 } else if (!sourceCurrency.equals(other.sourceCurrency))
155 if (sourceEquivalent == null) {
156 if (other.sourceEquivalent != null)
158 } else if (!sourceEquivalent.equals(other.sourceEquivalent))