001/**
002 * The MIT License (MIT)
003 *
004 * Copyright (c) 2015-2016 decimal4j (tools4j), Marco Terzer
005 *
006 * Permission is hereby granted, free of charge, to any person obtaining a copy
007 * of this software and associated documentation files (the "Software"), to deal
008 * in the Software without restriction, including without limitation the rights
009 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
010 * copies of the Software, and to permit persons to whom the Software is
011 * furnished to do so, subject to the following conditions:
012 *
013 * The above copyright notice and this permission notice shall be included in all
014 * copies or substantial portions of the Software.
015 *
016 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
017 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
018 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
019 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
020 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
021 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
022 * SOFTWARE.
023 */
024package org.decimal4j.generic;
025
026import java.math.BigDecimal;
027import java.math.BigInteger;
028import java.math.RoundingMode;
029import java.util.Objects;
030
031import org.decimal4j.api.Decimal;
032import org.decimal4j.api.MutableDecimal;
033import org.decimal4j.factory.DecimalFactory;
034import org.decimal4j.factory.Factories;
035import org.decimal4j.scale.ScaleMetrics;
036
037/**
038 * <tt>GenericDecimalFactory</tt> is a {@link DecimalFactory} for generic
039 * decimal values. Different generic decimal instances of the same class can
040 * have different scales as opposed to the decimal values defined in the
041 * {@code immutable} and {@code mutable} packages.
042 * <p>
043 * The recommended way to create a generic factory is via
044 * {@link Factories#getGenericDecimalFactory(ScaleMetrics)}.
045 * 
046 * @param <S>
047 *            the scale metrics type associated with this decimal
048 * @see GenericImmutableDecimal
049 * @see GenericMutableDecimal
050 */
051public final class GenericDecimalFactory<S extends ScaleMetrics> implements DecimalFactory<S> {
052
053        private final S scaleMetrics;
054
055        /**
056         * Constructor with scale metrics argument.
057         * <p>
058         * <b>Note:</b> Application code should use
059         * {@link Factories#getGenericDecimalFactory(ScaleMetrics)} instead.
060         * 
061         * @param scaleMetrics
062         *            the scale metrics for the new generic factory.
063         */
064        public GenericDecimalFactory(S scaleMetrics) {
065                this.scaleMetrics = Objects.requireNonNull(scaleMetrics, "scaleMetrics cannot be null");
066        }
067
068        @Override
069        public S getScaleMetrics() {
070                return scaleMetrics;
071        }
072        
073        @Override
074        public int getScale() {
075                return getScaleMetrics().getScale();
076        }
077
078        @SuppressWarnings("unchecked")
079        @Override
080        public Class<? extends GenericImmutableDecimal<S>> immutableType() {
081                return (Class<? extends GenericImmutableDecimal<S>>) (Class<?>) GenericImmutableDecimal.class;
082        }
083
084        @SuppressWarnings("unchecked")
085        @Override
086        public Class<? extends MutableDecimal<S>> mutableType() {
087                return (Class<? extends GenericMutableDecimal<S>>) (Class<?>) GenericMutableDecimal.class;
088        }
089
090        @Override
091        public GenericDecimalFactory<?> deriveFactory(int scale) {
092                return Factories.getGenericDecimalFactory(scale);
093        }
094
095        public <T extends ScaleMetrics> GenericDecimalFactory<T> deriveFactory(T scaleMetrics) {
096                return Factories.getGenericDecimalFactory(scaleMetrics);
097        }
098
099        @Override
100        public GenericImmutableDecimal<S> valueOf(long value) {
101                return new GenericImmutableDecimal<S>(scaleMetrics, scaleMetrics.getDefaultCheckedArithmetic().fromLong(value));
102        }
103
104        @Override
105        public GenericImmutableDecimal<S> valueOf(float value) {
106                return new GenericImmutableDecimal<S>(scaleMetrics, scaleMetrics.getDefaultCheckedArithmetic().fromFloat(value));
107        }
108
109        @Override
110        public GenericImmutableDecimal<S> valueOf(float value, RoundingMode roundingMode) {
111                return new GenericImmutableDecimal<S>(scaleMetrics, scaleMetrics.getCheckedArithmetic(roundingMode).fromFloat(value));
112        }
113
114        @Override
115        public GenericImmutableDecimal<S> valueOf(double value) {
116                return new GenericImmutableDecimal<S>(scaleMetrics, scaleMetrics.getDefaultCheckedArithmetic().fromDouble(value));
117        }
118
119        @Override
120        public GenericImmutableDecimal<S> valueOf(double value, RoundingMode roundingMode) {
121                return new GenericImmutableDecimal<S>(scaleMetrics, scaleMetrics.getCheckedArithmetic(roundingMode).fromDouble(value));
122        }
123
124        @Override
125        public GenericImmutableDecimal<S> valueOf(BigInteger value) {
126                return new GenericImmutableDecimal<S>(scaleMetrics, scaleMetrics.getDefaultCheckedArithmetic().fromBigInteger(value));
127        }
128
129        @Override
130        public GenericImmutableDecimal<S> valueOf(BigDecimal value) {
131                return new GenericImmutableDecimal<S>(scaleMetrics, scaleMetrics.getDefaultCheckedArithmetic().fromBigDecimal(value));
132        }
133
134        @Override
135        public GenericImmutableDecimal<S> valueOf(BigDecimal value, RoundingMode roundingMode) {
136                return new GenericImmutableDecimal<S>(scaleMetrics, scaleMetrics.getCheckedArithmetic(roundingMode).fromBigDecimal(
137                                value));
138        }
139
140        @Override
141        public GenericImmutableDecimal<S> valueOf(Decimal<?> value) {
142                return new GenericImmutableDecimal<S>(scaleMetrics, scaleMetrics.getDefaultCheckedArithmetic().fromUnscaled(
143                                value.unscaledValue(), value.getScale()));
144        }
145
146        @Override
147        public GenericImmutableDecimal<S> valueOf(Decimal<?> value, RoundingMode roundingMode) {
148                return new GenericImmutableDecimal<S>(scaleMetrics, scaleMetrics.getCheckedArithmetic(roundingMode).fromUnscaled(
149                                value.unscaledValue(), value.getScale()));
150        }
151
152        @Override
153        public GenericImmutableDecimal<S> parse(String value) {
154                return new GenericImmutableDecimal<S>(scaleMetrics, scaleMetrics.getDefaultCheckedArithmetic().parse(value));
155        }
156
157        @Override
158        public GenericImmutableDecimal<S> parse(String value, RoundingMode roundingMode) {
159                return new GenericImmutableDecimal<S>(scaleMetrics, scaleMetrics.getCheckedArithmetic(roundingMode).parse(value));
160        }
161
162        @Override
163        public GenericImmutableDecimal<S> valueOfUnscaled(long unscaled) {
164                return new GenericImmutableDecimal<S>(scaleMetrics, unscaled);
165        }
166
167        @Override
168        public GenericImmutableDecimal<S> valueOfUnscaled(long unscaledValue, int scale) {
169                return new GenericImmutableDecimal<S>(scaleMetrics, scaleMetrics.getDefaultCheckedArithmetic().fromUnscaled(
170                                unscaledValue, scale));
171        }
172
173        @Override
174        public GenericImmutableDecimal<S> valueOfUnscaled(long unscaledValue, int scale, RoundingMode roundingMode) {
175                return new GenericImmutableDecimal<S>(scaleMetrics, scaleMetrics.getCheckedArithmetic(roundingMode).fromUnscaled(
176                                unscaledValue, scale));
177        }
178
179        @SuppressWarnings("unchecked")
180        @Override
181        public GenericImmutableDecimal<S>[] newArray(int length) {
182                return new GenericImmutableDecimal[length];
183        }
184
185        @Override
186        public GenericMutableDecimal<S> newMutable() {
187                return new GenericMutableDecimal<S>(scaleMetrics);
188        }
189
190        @SuppressWarnings("unchecked")
191        @Override
192        public GenericMutableDecimal<S>[] newMutableArray(int length) {
193                return new GenericMutableDecimal[length];
194        }
195}