001/*
002 * The MIT License (MIT)
003 *
004 * Copyright (c) 2015-2023 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.util.Objects;
027
028import org.decimal4j.api.Decimal;
029import org.decimal4j.api.MutableDecimal;
030import org.decimal4j.base.AbstractMutableDecimal;
031import org.decimal4j.factory.Factories;
032import org.decimal4j.scale.ScaleMetrics;
033import org.decimal4j.scale.Scales;
034
035/**
036 * <code>GenericMutableDecimal</code> is an {@link MutableDecimal} implemented in a
037 * generic way, that is, different instances can have different scales. In
038 * contrast the classes defined in the {@code mutable} package have have no
039 * generic parameter as they have a fixed scale per class.
040 * 
041 * @param <S>
042 *            the scale metrics type associated with this Decimal
043 */
044public final class GenericMutableDecimal<S extends ScaleMetrics>
045                extends AbstractMutableDecimal<S, GenericMutableDecimal<S>> implements Cloneable {
046
047        private static final long serialVersionUID = 1L;
048
049        private final S scaleMetrics;
050
051        /**
052         * Creates a new {@code GenericMutableDecimal} with value zero.
053         * 
054         * @param scaleMetrics
055         *            the metrics object defining the scale for the zero value
056         */
057        public GenericMutableDecimal(S scaleMetrics) {
058                this(scaleMetrics, 0);
059        }
060
061        /**
062         * Creates a new {@code GenericMutableDecimal} with the same value and scale
063         * as the given {@code decimal} argument.
064         * 
065         * @param decimal
066         *            the numeric value to assign to the created mutable Decimal
067         */
068        public GenericMutableDecimal(Decimal<S> decimal) {
069                this(decimal.getScaleMetrics(), decimal.unscaledValue());
070        }
071
072        /**
073         * Creates a new {@code GenericMutableDecimal} with the scale specified by
074         * the given {@code scaleMetrics} argument. The numeric value of new the
075         * Decimal is <code>unscaledValue &times; 10<sup>-scale</sup></code>
076         * 
077         * @param scaleMetrics
078         *            the metrics object defining the scale for the new value
079         * @param unscaledValue
080         *            the unscaled long value representing the new Decimal's
081         *            numerical value before applying the scale factor
082         */
083        public GenericMutableDecimal(S scaleMetrics, long unscaledValue) {
084                super(unscaledValue);
085                this.scaleMetrics = Objects.requireNonNull(scaleMetrics, "scaleMetrics cannot be null");
086        }
087
088        /**
089         * Creates and returns a new {@code GenericMutableDecimal} with the same
090         * value and scale as the given {@code decimal} argument.
091         * 
092         * @param decimal
093         *            the numeric value to assign to the created mutable Decimal
094         * @param <S>
095         *            the scale metrics type
096         * @return a new generic mutable Decimal value with scale and value copied
097         *         from the {@code decimal} argument
098         */
099        public static <S extends ScaleMetrics> GenericMutableDecimal<S> valueOf(Decimal<S> decimal) {
100                return new GenericMutableDecimal<S>(decimal);
101        }
102
103        /**
104         * Creates and returns a new {@code GenericMutableDecimal} with the scale
105         * specified by the given {@code scaleMetrics} argument. The numeric value
106         * of new the Decimal is
107         * <code>unscaledValue &times; 10<sup>-scale</sup></code>
108         * 
109         * @param scaleMetrics
110         *            the metrics object defining the scale for the new value
111         * @param unscaled
112         *            the unscaled long value representing the new Decimal's
113         *            numerical value before applying the scale factor
114         * @param <S>
115         *            the scale metrics type
116         * @return a new Decimal value representing
117         *         <code>unscaledValue &times; 10<sup>-scale</sup></code>
118         */
119        public static <S extends ScaleMetrics> GenericMutableDecimal<S> valueOfUnscaled(S scaleMetrics, long unscaled) {
120                return new GenericMutableDecimal<S>(scaleMetrics, unscaled);
121        }
122
123        /**
124         * Creates and returns a new {@code GenericMutableDecimal} with the
125         * specified {@code scale} and value. The numeric value of new the Decimal
126         * is <code>unscaledValue &times; 10<sup>-scale</sup></code>
127         * 
128         * @param scale
129         *            the scale for the new value
130         * @param unscaled
131         *            the unscaled long value representing the new Decimal's
132         *            numerical value before applying the scale factor
133         * @return a new Decimal value representing
134         *         <code>unscaledValue &times; 10<sup>-scale</sup></code>
135         */
136        public static GenericMutableDecimal<?> valueOfUnscaled(int scale, long unscaled) {
137                return valueOfUnscaled(Scales.getScaleMetrics(scale), unscaled);
138        }
139
140        @Override
141        protected GenericMutableDecimal<S> create(long unscaled) {
142                return new GenericMutableDecimal<S>(scaleMetrics, unscaled);
143        }
144
145        @SuppressWarnings("unchecked")
146        @Override
147        protected GenericMutableDecimal<S>[] createArray(int length) {
148                return new GenericMutableDecimal[length];
149        }
150
151        @Override
152        protected GenericMutableDecimal<S> self() {
153                return this;
154        }
155
156        @Override
157        public S getScaleMetrics() {
158                return scaleMetrics;
159        }
160
161        @Override
162        public int getScale() {
163                return scaleMetrics.getScale();
164        }
165
166        @Override
167        public GenericDecimalFactory<S> getFactory() {
168                return Factories.getGenericDecimalFactory(scaleMetrics);
169        }
170
171        @Override
172        public GenericMutableDecimal<S> clone() {
173                return new GenericMutableDecimal<S>(scaleMetrics, unscaledValue());
174        }
175
176        @Override
177        public GenericImmutableDecimal<S> toImmutableDecimal() {
178                return new GenericImmutableDecimal<S>(this);
179        }
180
181        @Override
182        public GenericMutableDecimal<S> toMutableDecimal() {
183                return this;
184        }
185}