001/** 002 * Copyright (c) 2012, 2015, Credit Suisse (Anatole Tresch), Werner Keil and others by the @author tag. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 005 * use this file except in compliance with the License. You may obtain a copy of 006 * the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 013 * License for the specific language governing permissions and limitations under 014 * the License. 015 */ 016package org.javamoney.moneta; 017 018import javax.money.MonetaryAmount; 019import javax.money.MonetaryOperator; 020import java.math.BigDecimal; 021import java.math.MathContext; 022import java.math.RoundingMode; 023import java.util.Objects; 024 025import static java.util.Objects.requireNonNull; 026 027/** 028 * <p>This implementation uses a scale and {@link RoundingMode} and precision to does the rounding operations. The implementation will use both the <b>scale</b> and <b>precision</b>, in other words, the number of digits to the right of the decimal point and the number of digits.</p> 029 * <p>The derived class will implements the {@link RoundedMoney} with this rounding monetary operator</p> 030 * <pre> 031 * {@code 032 * int scale = 3; 033 * int precision = 5; 034 * MathContext mathContext = new MathContext(precision, RoundingMode.HALF_EVEN); 035 * MonetaryOperator monetaryOperator = PrecisionScaleRoundedOperator.of(scale, mathContext); 036 * CurrencyUnit real = Monetary.getCurrency("BRL"); 037 * MonetaryAmount money = Money.of(BigDecimal.valueOf(35.34567), real); 038 * MonetaryAmount result = monetaryOperator.apply(money); // BRL 35.346 039 * 040 * } 041* </pre> 042 * <p>Case the parameter in {@link MonetaryOperator#apply(MonetaryAmount)} be null, the apply will return a {@link NullPointerException}</p> 043 * @author Otavio Santana 044 * @see {@link PrecisionScaleRoundedOperator#of(int, MathContext)} 045 * @see {@link RoundedMoney} 046 * @see {@link MonetaryOperator} 047 * @see {@link BigDecimal#scale()} 048 * @see {@link MathContext} 049 * @see {@link BigDecimal#precision()} 050 * @since 1.0.1 051 * @deprecated Do not use, access is only provided for backward compatibility and will be removed. 052 */ 053@Deprecated 054public final class PrecisionScaleRoundedOperator implements MonetaryOperator { 055 056 private final PrecisionContextRoundedOperator mathContextOperator; 057 058 private final ScaleRoundedOperator scaleRoundedOperator; 059 060 private final int scale; 061 062 private final MathContext mathContext; 063 064 private PrecisionScaleRoundedOperator(int scale, MathContext mathContext) { 065 this.scale = scale; 066 this.mathContext = mathContext; 067 this.mathContextOperator = PrecisionContextRoundedOperator.of(mathContext); 068 this.scaleRoundedOperator = ScaleRoundedOperator.of(scale, mathContext.getRoundingMode()); 069 } 070 071 /** 072 * Creates the rounded Operator from scale and roundingMode 073 * @param mathContext 074 * @return the {@link MonetaryOperator} using the scale and {@link RoundingMode} used in parameter 075 * @throws NullPointerException when the {@link MathContext} is null 076 * @throws IllegalArgumentException if {@link MathContext#getPrecision()} is lesser than zero 077 * @throws IllegalArgumentException if {@link MathContext#getRoundingMode()} is {@link RoundingMode#UNNECESSARY} 078 * @see {@linkplain RoundingMode} 079 */ 080 public static PrecisionScaleRoundedOperator of(int scale, MathContext mathContext) { 081 082 Objects.requireNonNull(mathContext); 083 084 if(RoundingMode.UNNECESSARY.equals(mathContext.getRoundingMode())) { 085 throw new IllegalArgumentException("To create the ScaleRoundedOperator you cannot use the RoundingMode.UNNECESSARY on MathContext"); 086 } 087 088 if(mathContext.getPrecision() <= 0) { 089 throw new IllegalArgumentException("To create the ScaleRoundedOperator you cannot use the zero precision on MathContext"); 090 } 091 return new PrecisionScaleRoundedOperator(scale, mathContext); 092 } 093 094 @Override 095 public MonetaryAmount apply(MonetaryAmount amount) { 096 return scaleRoundedOperator.apply(requireNonNull(amount)).with(mathContextOperator); 097 } 098 099 public int getScale() { 100 return scale; 101 } 102 103 public MathContext getMathContext() { 104 return mathContext; 105 } 106 107 @Override 108 public String toString() { 109 StringBuilder sb = new StringBuilder(); 110 sb.append(PrecisionScaleRoundedOperator.class.getName()).append('{') 111 .append("scale:").append(Integer.toString(scale)).append(',') 112 .append("mathContext:").append(mathContext).append('}'); 113 return sb.toString(); 114 } 115 116}