japod@6: package org.apidesign.apifest08.currency; japod@6: japod@6: import java.math.BigDecimal; japod@6: import java.math.RoundingMode; japod@6: japod@6: /** japod@6: * A rate of conversion from one currency to another. japod@6: * @author jdvorak japod@6: */ japod@6: public class ConversionRate { japod@6: japod@6: private final MonetaryAmount srcUnitAmount; japod@6: private final MonetaryAmount tgtUnitAmount; japod@6: private final int tgtScale; japod@6: private final RoundingMode roundingMode; japod@6: japod@6: /** japod@6: * A new conversion rate that gives tgtUnitAmount per every srcUnitAmount. japod@6: * @param srcUnitAmount the amount of source currency japod@6: * @param tgtUnitAmount the corresponding amount of target currency japod@6: * @param tgtScale the scale of the target amounts japod@6: * @param roundingMode the rounding mode to use when producing the target amounts japod@6: */ japod@6: public ConversionRate( final MonetaryAmount srcUnitAmount, final MonetaryAmount tgtUnitAmount, final int targetScale, final RoundingMode roundingMode ) { japod@6: this.srcUnitAmount = srcUnitAmount; japod@6: this.tgtUnitAmount = tgtUnitAmount; japod@6: this.tgtScale = targetScale; japod@6: this.roundingMode = roundingMode; japod@6: } japod@6: japod@6: /** japod@6: * A new conversion rate that gives tgtUnitAmount per every srcUnitAmount, default number of fraction digits and the given rounding mode. japod@6: * @param srcUnitAmount the amount of source currency japod@6: * @param tgtUnitAmount the corresponding amount of target currency japod@6: * @param roundingMode the rounding mode to use japod@6: */ japod@6: public ConversionRate( final MonetaryAmount srcUnitAmount, final MonetaryAmount tgtUnitAmount, final RoundingMode roundingMode ) { japod@6: this( srcUnitAmount, tgtUnitAmount, tgtUnitAmount.getCurrency().getDefaultFractionDigits(), roundingMode ); japod@6: } japod@6: japod@6: /** japod@6: * A new conversion rate that gives tgtUnitAmount per every srcUnitAmount, default number of fraction digits and {@link RoundingMode#HALF_EVEN}. japod@6: * @param srcUnitAmount the amount of source currency japod@6: * @param tgtUnitAmount the corresponding amount of target currency japod@6: */ japod@6: public ConversionRate( final MonetaryAmount srcUnitAmount, final MonetaryAmount tgtUnitAmount ) { japod@6: this( srcUnitAmount, tgtUnitAmount, RoundingMode.HALF_EVEN ); japod@6: } japod@6: japod@6: public RoundingMode getRoundingMode() { japod@6: return roundingMode; japod@6: } japod@6: japod@6: public MonetaryAmount getSrcUnitAmount() { japod@6: return srcUnitAmount; japod@6: } japod@6: japod@6: public int getTgtScale() { japod@6: return tgtScale; japod@6: } japod@6: japod@6: public MonetaryAmount getTgtUnitAmount() { japod@6: return tgtUnitAmount; japod@6: } japod@6: japod@6: /** japod@6: * Multiplies the given amount with the given rate. japod@6: * @param srcAmount japod@6: * @return japod@6: */ japod@6: public BigDecimal convert( final BigDecimal srcAmount ) { japod@6: return srcAmount japod@6: .multiply( tgtUnitAmount.getAmount() ) japod@6: .divide( srcUnitAmount.getAmount(), tgtScale, roundingMode ); japod@6: } japod@6: japod@6: /** japod@6: * Creates a monetary amount that corresponds to the given source amount multiplied by the rate. japod@6: * @param srcAmount the source amount japod@6: * @return the monetary amount in the target currency japod@6: * @throws IllegalArgumentException if the currency of srcAmount is not equal to the source currency of this rate japod@6: */ japod@6: public MonetaryAmount convert( final MonetaryAmount srcAmount ) { japod@6: if ( srcUnitAmount.getCurrency().equals( srcAmount.getCurrency() ) ) { japod@6: return new MonetaryAmount( convert( srcAmount.getAmount() ), tgtUnitAmount.getCurrency() ); japod@6: } else { japod@6: throw new IllegalArgumentException( "This rate converts from " + srcUnitAmount.getCurrency() + ", but a conversion from " + srcAmount.getCurrency() + " is attempted" ); japod@6: } japod@6: } japod@6: japod@6: }