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.function;
017
018import static java.util.Objects.requireNonNull;
019
020import java.math.BigDecimal;
021import java.math.MathContext;
022import java.math.RoundingMode;
023import java.util.Objects;
024
025import javax.money.MonetaryAmount;
026import javax.money.MonetaryOperator;
027
028/**
029 * <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>
030 * <p>The derived class will implements the {@link org.javamoney.moneta.RoundedMoney} with this rounding monetary operator</p>
031 *  <pre>
032 *   {@code
033 *     int scale = 3;
034 *     int precision = 5;
035 *     MathContext mathContext = new MathContext(precision, RoundingMode.HALF_EVEN);
036 *     MonetaryOperator monetaryOperator = PrecisionScaleRoundedOperator.of(scale, mathContext);
037 *     CurrencyUnit real = Monetary.getCurrency("BRL");
038 *     MonetaryAmount money = Money.of(BigDecimal.valueOf(35.34567), real);
039 *     MonetaryAmount result = monetaryOperator.apply(money); // BRL 35.346
040 *
041 *    }
042* </pre>
043 * <p>Case the parameter in {@link MonetaryOperator#apply(MonetaryAmount)} be null, the apply will return a {@link NullPointerException}</p>
044 * @author Otavio Santana
045 * @see {@link PrecisionScaleRoundedOperator#of(int, MathContext)}
046 * @see {@link org.javamoney.moneta.RoundedMoney}
047 * @see {@link MonetaryOperator}
048 * @see {@link BigDecimal#scale()}
049 * @see {@link MathContext}
050 * @see {@link BigDecimal#precision()}
051 * @since 1.0.1
052 * @deprecated Do not use, access is only provided for backward compatibility and will be removed.
053 */
054@Deprecated
055public final class PrecisionScaleRoundedOperator implements MonetaryOperator {
056
057        private final PrecisionContextRoundedOperator mathContextOperator;
058
059        private final ScaleRoundedOperator scaleRoundedOperator;
060
061        private final int scale;
062
063        private final MathContext mathContext;
064
065        private PrecisionScaleRoundedOperator(int scale, MathContext mathContext) {
066                this.scale = scale;
067                this.mathContext = mathContext;
068                this.mathContextOperator = PrecisionContextRoundedOperator.of(mathContext);
069                this.scaleRoundedOperator = ScaleRoundedOperator.of(scale, mathContext.getRoundingMode());
070        }
071
072        /**
073         * Creates the rounded Operator from scale and roundingMode
074         * @param mathContext
075         * @return the {@link MonetaryOperator} using the scale and {@link RoundingMode} used in parameter
076         * @throws NullPointerException when the {@link MathContext} is null
077         * @throws IllegalArgumentException if {@link MathContext#getPrecision()} is lesser than zero
078         * @throws IllegalArgumentException if {@link MathContext#getRoundingMode()} is {@link RoundingMode#UNNECESSARY}
079         * @see {@linkplain RoundingMode}
080         */
081        public static PrecisionScaleRoundedOperator of(int scale, MathContext mathContext) {
082
083                Objects.requireNonNull(mathContext);
084
085                if(RoundingMode.UNNECESSARY.equals(mathContext.getRoundingMode())) {
086                   throw new IllegalArgumentException("To create the ScaleRoundedOperator you cannot use the RoundingMode.UNNECESSARY on MathContext");
087                }
088
089                if(mathContext.getPrecision() <= 0) {
090                        throw new IllegalArgumentException("To create the ScaleRoundedOperator you cannot use the zero precision on MathContext");
091                }
092                return new PrecisionScaleRoundedOperator(scale, mathContext);
093        }
094
095        @Override
096        public MonetaryAmount apply(MonetaryAmount amount) {
097                return scaleRoundedOperator.apply(requireNonNull(amount)).with(mathContextOperator);
098        }
099
100        public int getScale() {
101                return scale;
102        }
103
104        public MathContext getMathContext() {
105                return mathContext;
106        }
107
108        @Override
109        public String toString() {
110                StringBuilder sb = new StringBuilder();
111                sb.append(PrecisionScaleRoundedOperator.class.getName()).append('{')
112                .append("scale:").append(Integer.toString(scale)).append(',')
113                .append("mathContext:").append(mathContext).append('}');
114                return sb.toString();
115        }
116
117}