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}