japod@57
|
1 |
/*
|
japod@57
|
2 |
* To change this template, choose Tools | Templates
|
japod@57
|
3 |
* and open the template in the editor.
|
japod@57
|
4 |
*/
|
japod@57
|
5 |
|
japod@57
|
6 |
package org.apidesign.apifest08.currency.anothervendor;
|
japod@57
|
7 |
|
japod@57
|
8 |
import java.math.BigDecimal;
|
japod@57
|
9 |
import java.util.Currency;
|
japod@57
|
10 |
import java.util.Iterator;
|
japod@57
|
11 |
import org.apidesign.apifest08.currency.Convertor;
|
japod@57
|
12 |
import org.apidesign.apifest08.currency.IllegalRequestSubtypeException;
|
japod@57
|
13 |
import org.apidesign.apifest08.currency.MonetaryAmount;
|
japod@57
|
14 |
|
japod@57
|
15 |
|
japod@57
|
16 |
/**
|
japod@57
|
17 |
* A convertor that changes the rate by a step amount on every conversion it performs.
|
japod@57
|
18 |
* @author jdvorak
|
japod@57
|
19 |
*/
|
japod@57
|
20 |
public class ZigZaggingBidirectionalConvertor implements Convertor {
|
japod@57
|
21 |
|
japod@57
|
22 |
private final MonetaryAmount srcRateAmount;
|
japod@57
|
23 |
|
japod@57
|
24 |
private final Currency tgtCurrency;
|
japod@57
|
25 |
|
japod@57
|
26 |
private final Iterator<BigDecimal> rateIterator;
|
japod@57
|
27 |
|
japod@57
|
28 |
/**
|
japod@57
|
29 |
* Costructor with the precise amounts.
|
japod@57
|
30 |
* @param srcRateAmount
|
japod@57
|
31 |
* @param tgtCurrency
|
japod@57
|
32 |
* @param startAmount
|
japod@57
|
33 |
* @param endAmount
|
japod@57
|
34 |
* @param stepAmount
|
japod@57
|
35 |
*/
|
japod@57
|
36 |
public ZigZaggingBidirectionalConvertor( final MonetaryAmount srcRateAmount, final Currency tgtCurrency, final BigDecimal startAmount, final BigDecimal endAmount, final BigDecimal stepAmount ) {
|
japod@57
|
37 |
this.srcRateAmount = srcRateAmount;
|
japod@57
|
38 |
this.tgtCurrency = tgtCurrency;
|
japod@57
|
39 |
this.rateIterator = new ZigZaggingBigDecimalIterator( startAmount, endAmount, stepAmount );
|
japod@57
|
40 |
}
|
japod@57
|
41 |
|
japod@57
|
42 |
/**
|
japod@57
|
43 |
* Do the conversion; updates the rate.
|
japod@57
|
44 |
* @param req
|
japod@57
|
45 |
* @return
|
japod@57
|
46 |
* @throws org.apidesign.apifest08.currency.IllegalRequestSubtypeException
|
japod@57
|
47 |
*/
|
japod@57
|
48 |
public synchronized ConversionResult convert( ConversionRequest req ) throws IllegalRequestSubtypeException {
|
japod@57
|
49 |
if ( tgtCurrency.equals( req.getTgtCurrency() ) ) {
|
japod@57
|
50 |
if ( srcRateAmount.getCurrency().equals( req.getSrcAmount().getCurrency() ) ) {
|
japod@57
|
51 |
final BigDecimal tgtRateAmount = rateIterator.next();
|
japod@57
|
52 |
final BigDecimal tgtAmount = req.getSrcAmount().getAmount().multiply( tgtRateAmount ).divide( srcRateAmount.getAmount() );
|
japod@57
|
53 |
return new ConversionResult( new MonetaryAmount( tgtAmount, tgtCurrency ) );
|
japod@57
|
54 |
}
|
japod@57
|
55 |
}
|
japod@57
|
56 |
if ( srcRateAmount.getCurrency().equals( req.getTgtCurrency() ) ) {
|
japod@57
|
57 |
if ( tgtCurrency.equals( req.getSrcAmount().getCurrency() ) ) {
|
japod@57
|
58 |
final BigDecimal tgtRateAmount = rateIterator.next();
|
japod@57
|
59 |
final BigDecimal tgtAmount = req.getSrcAmount().getAmount().multiply( srcRateAmount.getAmount() ).divide( tgtRateAmount );
|
japod@57
|
60 |
return new ConversionResult( new MonetaryAmount( tgtAmount, srcRateAmount.getCurrency() ) );
|
japod@57
|
61 |
}
|
japod@57
|
62 |
}
|
japod@57
|
63 |
return new ConversionResult( null );
|
japod@57
|
64 |
}
|
japod@57
|
65 |
|
japod@57
|
66 |
}
|
japod@57
|
67 |
|
japod@57
|
68 |
/**
|
japod@57
|
69 |
* An iterator that goes zig first, then zag, then zig again, then zag again, ad libitum.
|
japod@57
|
70 |
* @author jdvorak
|
japod@57
|
71 |
*/
|
japod@57
|
72 |
class ZigZaggingBigDecimalIterator implements Iterator<BigDecimal> {
|
japod@57
|
73 |
|
japod@57
|
74 |
private BigDecimal zigBounce;
|
japod@57
|
75 |
|
japod@57
|
76 |
private BigDecimal zagBounce;
|
japod@57
|
77 |
|
japod@57
|
78 |
private BigDecimal step;
|
japod@57
|
79 |
|
japod@57
|
80 |
private BigDecimal currentValue;
|
japod@57
|
81 |
|
japod@57
|
82 |
protected ZigZaggingBigDecimalIterator( final BigDecimal zagBounce, final BigDecimal zigBounce, final BigDecimal step ) {
|
japod@57
|
83 |
this. zigBounce = zigBounce;
|
japod@57
|
84 |
this.zagBounce = zagBounce;
|
japod@57
|
85 |
this.currentValue = zagBounce;
|
japod@57
|
86 |
this.step = step;
|
japod@57
|
87 |
|
japod@57
|
88 |
if ( zigBounce == null ) {
|
japod@57
|
89 |
throw new NullPointerException( "zigAmount" );
|
japod@57
|
90 |
}
|
japod@57
|
91 |
if ( zagBounce == null ) {
|
japod@57
|
92 |
throw new NullPointerException( "zagAmount" );
|
japod@57
|
93 |
}
|
japod@57
|
94 |
if ( step == null ) {
|
japod@57
|
95 |
throw new NullPointerException( "stepAmount" );
|
japod@57
|
96 |
}
|
japod@57
|
97 |
final int stepSign = step.signum();
|
japod@57
|
98 |
if ( stepSign == 0 ) {
|
japod@57
|
99 |
throw new IllegalArgumentException( "stepAmount can't be zero" );
|
japod@57
|
100 |
}
|
japod@57
|
101 |
if ( stepSign * zigBounce.compareTo( zagBounce ) < 0 ) {
|
japod@57
|
102 |
throw new IllegalArgumentException( "stepAmount shall have the same sign as endAmount - startAmount" );
|
japod@57
|
103 |
}
|
japod@57
|
104 |
}
|
japod@57
|
105 |
|
japod@57
|
106 |
public boolean hasNext() {
|
japod@57
|
107 |
return true;
|
japod@57
|
108 |
}
|
japod@57
|
109 |
|
japod@57
|
110 |
public BigDecimal next() {
|
japod@57
|
111 |
final BigDecimal result = currentValue;
|
japod@57
|
112 |
|
japod@57
|
113 |
currentValue = currentValue.add( step );
|
japod@57
|
114 |
final int stepSign = step.signum();
|
japod@57
|
115 |
final int currentMinusZigSign = currentValue.compareTo( zigBounce );
|
japod@57
|
116 |
if ( stepSign * currentMinusZigSign >= 0 ) {
|
japod@57
|
117 |
final BigDecimal temp = zigBounce;
|
japod@57
|
118 |
zigBounce = zagBounce;
|
japod@57
|
119 |
zagBounce = temp;
|
japod@57
|
120 |
step = step.negate();
|
japod@57
|
121 |
}
|
japod@57
|
122 |
|
japod@57
|
123 |
return result;
|
japod@57
|
124 |
}
|
japod@57
|
125 |
|
japod@57
|
126 |
public void remove() {
|
japod@57
|
127 |
throw new UnsupportedOperationException("Removal is not supported.");
|
japod@57
|
128 |
}
|
japod@57
|
129 |
|
japod@57
|
130 |
} |