japod@57: /* japod@57: * To change this template, choose Tools | Templates japod@57: * and open the template in the editor. japod@57: */ japod@57: japod@57: package org.apidesign.apifest08.currency.anothervendor; japod@57: japod@57: import java.math.BigDecimal; japod@57: import java.util.Currency; japod@57: import java.util.Iterator; japod@57: import org.apidesign.apifest08.currency.Convertor; japod@57: import org.apidesign.apifest08.currency.IllegalRequestSubtypeException; japod@57: import org.apidesign.apifest08.currency.MonetaryAmount; japod@57: japod@57: japod@57: /** japod@57: * A convertor that changes the rate by a step amount on every conversion it performs. japod@57: * @author jdvorak japod@57: */ japod@57: public class ZigZaggingBidirectionalConvertor implements Convertor { japod@57: japod@57: private final MonetaryAmount srcRateAmount; japod@57: japod@57: private final Currency tgtCurrency; japod@57: japod@57: private final Iterator rateIterator; japod@57: japod@57: /** japod@57: * Costructor with the precise amounts. japod@57: * @param srcRateAmount japod@57: * @param tgtCurrency japod@57: * @param startAmount japod@57: * @param endAmount japod@57: * @param stepAmount japod@57: */ japod@57: public ZigZaggingBidirectionalConvertor( final MonetaryAmount srcRateAmount, final Currency tgtCurrency, final BigDecimal startAmount, final BigDecimal endAmount, final BigDecimal stepAmount ) { japod@57: this.srcRateAmount = srcRateAmount; japod@57: this.tgtCurrency = tgtCurrency; japod@57: this.rateIterator = new ZigZaggingBigDecimalIterator( startAmount, endAmount, stepAmount ); japod@57: } japod@57: japod@57: /** japod@57: * Do the conversion; updates the rate. japod@57: * @param req japod@57: * @return japod@57: * @throws org.apidesign.apifest08.currency.IllegalRequestSubtypeException japod@57: */ japod@57: public synchronized ConversionResult convert( ConversionRequest req ) throws IllegalRequestSubtypeException { japod@57: if ( tgtCurrency.equals( req.getTgtCurrency() ) ) { japod@57: if ( srcRateAmount.getCurrency().equals( req.getSrcAmount().getCurrency() ) ) { japod@57: final BigDecimal tgtRateAmount = rateIterator.next(); japod@57: final BigDecimal tgtAmount = req.getSrcAmount().getAmount().multiply( tgtRateAmount ).divide( srcRateAmount.getAmount() ); japod@57: return new ConversionResult( new MonetaryAmount( tgtAmount, tgtCurrency ) ); japod@57: } japod@57: } japod@57: if ( srcRateAmount.getCurrency().equals( req.getTgtCurrency() ) ) { japod@57: if ( tgtCurrency.equals( req.getSrcAmount().getCurrency() ) ) { japod@57: final BigDecimal tgtRateAmount = rateIterator.next(); japod@57: final BigDecimal tgtAmount = req.getSrcAmount().getAmount().multiply( srcRateAmount.getAmount() ).divide( tgtRateAmount ); japod@57: return new ConversionResult( new MonetaryAmount( tgtAmount, srcRateAmount.getCurrency() ) ); japod@57: } japod@57: } japod@57: return new ConversionResult( null ); japod@57: } japod@57: japod@57: } japod@57: japod@57: /** japod@57: * An iterator that goes zig first, then zag, then zig again, then zag again, ad libitum. japod@57: * @author jdvorak japod@57: */ japod@57: class ZigZaggingBigDecimalIterator implements Iterator { japod@57: japod@57: private BigDecimal zigBounce; japod@57: japod@57: private BigDecimal zagBounce; japod@57: japod@57: private BigDecimal step; japod@57: japod@57: private BigDecimal currentValue; japod@57: japod@57: protected ZigZaggingBigDecimalIterator( final BigDecimal zagBounce, final BigDecimal zigBounce, final BigDecimal step ) { japod@57: this. zigBounce = zigBounce; japod@57: this.zagBounce = zagBounce; japod@57: this.currentValue = zagBounce; japod@57: this.step = step; japod@57: japod@57: if ( zigBounce == null ) { japod@57: throw new NullPointerException( "zigAmount" ); japod@57: } japod@57: if ( zagBounce == null ) { japod@57: throw new NullPointerException( "zagAmount" ); japod@57: } japod@57: if ( step == null ) { japod@57: throw new NullPointerException( "stepAmount" ); japod@57: } japod@57: final int stepSign = step.signum(); japod@57: if ( stepSign == 0 ) { japod@57: throw new IllegalArgumentException( "stepAmount can't be zero" ); japod@57: } japod@57: if ( stepSign * zigBounce.compareTo( zagBounce ) < 0 ) { japod@57: throw new IllegalArgumentException( "stepAmount shall have the same sign as endAmount - startAmount" ); japod@57: } japod@57: } japod@57: japod@57: public boolean hasNext() { japod@57: return true; japod@57: } japod@57: japod@57: public BigDecimal next() { japod@57: final BigDecimal result = currentValue; japod@57: japod@57: currentValue = currentValue.add( step ); japod@57: final int stepSign = step.signum(); japod@57: final int currentMinusZigSign = currentValue.compareTo( zigBounce ); japod@57: if ( stepSign * currentMinusZigSign >= 0 ) { japod@57: final BigDecimal temp = zigBounce; japod@57: zigBounce = zagBounce; japod@57: zagBounce = temp; japod@57: step = step.negate(); japod@57: } japod@57: japod@57: return result; japod@57: } japod@57: japod@57: public void remove() { japod@57: throw new UnsupportedOperationException("Removal is not supported."); japod@57: } japod@57: japod@57: }