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
018
019import java.math.BigDecimal;
020import java.math.MathContext;
021import java.util.concurrent.atomic.AtomicLong;
022
023import javax.money.MonetaryOperator;
024import javax.money.MonetaryQuery;
025
026/**
027 * This singleton class provides access to the predefined monetary functions.
028 * <p>
029 * The class is thread-safe, which is also true for all functions returned by
030 * this class.
031 *
032 * @author Anatole Tresch
033 * @deprecated use {@link ConversionOperators} or {@link MonetaryQuery} instead.
034 */
035@Deprecated
036public final class MonetaryUtil {
037    /**
038     * defaulkt Math context used.
039     */
040    private static final MathContext DEFAULT_MATH_CONTEXT = initDefaultMathContext();
041    /**
042     * Shared reciprocal instance.
043     */
044    private static final ReciprocalOperator RECIPROCAL = new ReciprocalOperator();
045
046    /**
047     * The shared instance of this class.
048     */
049    private static final ExtractorMinorPartOperator MINORPART = new ExtractorMinorPartOperator();
050    /**
051     * SHared minor units class.
052     */
053    private static final ExtractorMinorPartQuery MINORUNITS = new ExtractorMinorPartQuery();
054    /**
055     * Shared major part instance.
056     */
057    private static final ExtractorMajorPartOperator MAJORPART = new ExtractorMajorPartOperator();
058    /**
059     * Shared major units instance.
060     */
061    private static final ExtractorMajorPartQuery MAJORUNITS = new ExtractorMajorPartQuery();
062
063    /**
064     * Private singleton constructor.
065     */
066    private MonetaryUtil() {
067        // Singleton constructor
068    }
069
070    /**
071     * Get {@link MathContext} for {@link Permil} instances.
072     *
073     * @return the {@link MathContext} to be used, by default
074     * {@link MathContext#DECIMAL64}.
075     */
076    private static MathContext initDefaultMathContext() {
077        // TODO Initialize default, e.g. by system properties, or better:
078        // classpath properties!
079        return MathContext.DECIMAL64;
080    }
081
082    /**
083     * Return a {@link MonetaryOperator} realizing the recorpocal value of
084     * {@code f(R) = 1/R}.
085     *
086     * @return the reciprocal operator, never {@code null}
087     */
088    public static MonetaryOperator reciprocal() {
089        return RECIPROCAL;
090    }
091
092    /**
093     * Factory method creating a new instance with the given {@code BigDecimal} permil value.
094     *
095     * @param decimal the decimal value of the permil operator being created.
096     * @return a new  {@code Permil} operator
097     */
098    public static MonetaryOperator permil(BigDecimal decimal) {
099        return new PermilOperator(decimal);
100    }
101
102    /**
103     * Factory method creating a new instance with the given {@code Number} permil value.
104     *
105     * @param number the number value of the permil operator being created.
106     * @return a new  {@code Permil} operator
107     */
108    public static MonetaryOperator permil(Number number) {
109        return permil(number, DEFAULT_MATH_CONTEXT);
110    }
111
112    /**
113     * Factory method creating a new instance with the given {@code Number} permil value.
114     *
115     * @param number the number value of the permil operator being created.
116     * @return a new  {@code Permil} operator
117     */
118    public static MonetaryOperator permil(Number number, MathContext mathContext) {
119        return new PermilOperator(getBigDecimal(number, mathContext));
120    }
121
122    /**
123     * Factory method creating a new instance with the given {@code BigDecimal} percent value.
124     *
125     * @param decimal the decimal value of the percent operator being created.
126     * @return a new  {@code Percent} operator
127     */
128    public static MonetaryOperator percent(BigDecimal decimal) {
129        return new PercentOperator(decimal); // TODO caching, e.g. array for 1-100 might
130        // work.
131    }
132
133    /**
134     * Factory method creating a new instance with the given {@code Number} percent value.
135     *
136     * @param number the number value of the percent operator being created.
137     * @return a new  {@code Percent} operator
138     */
139    public static MonetaryOperator percent(Number number) {
140        return percent(getBigDecimal(number, DEFAULT_MATH_CONTEXT));
141    }
142
143    /**
144     * Access the shared instance of {@link MinorPart} for use.
145     *
146     * @return the shared instance, never {@code null}.
147     */
148    public static MonetaryOperator minorPart() {
149        return MINORPART;
150    }
151
152    /**
153     * Access the shared instance of {@link MajorPart} for use.
154     *
155     * @return the shared instance, never {@code null}.
156     */
157    public static MonetaryOperator majorPart() {
158        return MAJORPART;
159    }
160
161    /**
162     * Access the shared instance of {@link MinorUnits} for use.
163     *
164     * @return the shared instance, never {@code null}.
165     */
166    public static MonetaryQuery<Long> minorUnits() {
167        return MINORUNITS;
168    }
169
170    /**
171     * Access the shared instance of {@link MajorUnits} for use.
172     *
173     * @return the shared instance, never {@code null}.
174     */
175    public static MonetaryQuery<Long> majorUnits() {
176        return MAJORUNITS;
177    }
178
179    /**
180     * Converts to {@link BigDecimal}, if necessary, or casts, if possible.
181     *
182     * @param num         The {@link Number}
183     * @param mathContext the {@link MathContext}
184     * @return the {@code number} as {@link BigDecimal}
185     */
186    private static BigDecimal getBigDecimal(Number num,
187                                            MathContext mathContext) {
188        if (num instanceof BigDecimal) {
189            return (BigDecimal) num;
190        }
191        if (num instanceof Long || num instanceof Integer
192                || num instanceof Byte || num instanceof AtomicLong) {
193            return BigDecimal.valueOf(num.longValue());
194        }
195        if (num instanceof Float || num instanceof Double) {
196            return new BigDecimal(num.toString());
197        }
198        try {
199            // Avoid imprecise conversion to double value if at all possible
200            return new BigDecimal(num.toString(), mathContext);
201        } catch (NumberFormatException ignored) {
202        }
203        return BigDecimal.valueOf(num.doubleValue());
204    }
205}