-
Notifications
You must be signed in to change notification settings - Fork 213
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introduced BigDecimalConverter #4557
Changes from 5 commits
9a6a439
00f654a
a46bdbe
81fed09
5e8b811
e10a5c5
a4d60b4
45d1c0b
7ce8334
761dd6f
72e2eff
eab7236
aed99af
19d82b4
c399c06
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package org.opensearch.dataprepper.typeconverter; | ||
|
||
import java.math.BigDecimal; | ||
import java.math.RoundingMode; | ||
|
||
/** | ||
* Converter class for BigDecimal data type. By default, it applies zero scaling keeping the original value as it is. | ||
* If required, the scale can be set using the setScale method. | ||
*/ | ||
public class BigDecimalConverter implements TypeConverter<BigDecimal> { | ||
// Scale declared here becomes the state of this converter. | ||
// If the same instance of the converter is used for multiple conversions, | ||
// scale value set will be preserved and applied on the next conversion. | ||
private int scale = 0; | ||
|
||
public void setScale(int scale) { | ||
this.scale = scale; | ||
} | ||
|
||
public BigDecimal convert(Object source) throws IllegalArgumentException { | ||
BigDecimal result = null; | ||
if (source instanceof String) { | ||
result = new BigDecimal((String)source); | ||
} | ||
else if (source instanceof Float) { | ||
result = BigDecimal.valueOf((Float)source); | ||
} | ||
else if (source instanceof Double) { | ||
result = BigDecimal.valueOf((Double)source); | ||
} | ||
else if (source instanceof Boolean) { | ||
result = ((Boolean)source) ? BigDecimal.valueOf(1L) : BigDecimal.valueOf(0L); | ||
} | ||
else if (source instanceof Integer) { | ||
result = BigDecimal.valueOf((Integer)source); | ||
} | ||
else if (source instanceof Long) { | ||
result = BigDecimal.valueOf((Long)source); | ||
} | ||
else if (source instanceof BigDecimal) { | ||
result = ((BigDecimal)source); | ||
} | ||
|
||
if(result!=null) { | ||
if(scale!=0) { | ||
result = result.setScale(scale, RoundingMode.HALF_EVEN); | ||
} | ||
return result; | ||
} | ||
throw new IllegalArgumentException("Unsupported type conversion. From Source class: " + source.getClass() + " to BigDecimal"); | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package org.opensearch.dataprepper.typeconverter; | ||
|
||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.params.ParameterizedTest; | ||
import org.junit.jupiter.params.provider.Arguments; | ||
import org.junit.jupiter.params.provider.MethodSource; | ||
|
||
import java.math.BigDecimal; | ||
import java.math.RoundingMode; | ||
import java.util.Collections; | ||
import java.util.Map; | ||
import java.util.stream.Stream; | ||
|
||
import static org.hamcrest.CoreMatchers.equalTo; | ||
import static org.hamcrest.MatcherAssert.assertThat; | ||
import static org.junit.jupiter.api.Assertions.assertThrows; | ||
|
||
public class BigDecimalConverterTests { | ||
@Test | ||
void testStringToBigDecimalConversion() { | ||
BigDecimalConverter converter = new BigDecimalConverter(); | ||
final String stringConstant = "12345678912.12345"; | ||
assertThat(converter.convert(stringConstant), equalTo(new BigDecimal(stringConstant))); | ||
} | ||
|
||
@Test | ||
void testIntegerToBigDecimalConversion() { | ||
BigDecimalConverter converter = new BigDecimalConverter(); | ||
final int intConstant = 12345; | ||
assertThat(converter.convert(intConstant), equalTo(BigDecimal.valueOf(intConstant))); | ||
} | ||
|
||
@Test | ||
void testLongToBigDecimalConversion() { | ||
BigDecimalConverter converter = new BigDecimalConverter(); | ||
final long longConstant = 123456789012L; | ||
assertThat(converter.convert(longConstant).longValue(), equalTo(longConstant)); | ||
} | ||
|
||
@Test | ||
void testBooleanToBigDecimalConversion() { | ||
BigDecimalConverter converter = new BigDecimalConverter(); | ||
final Boolean boolFalseConstant = false; | ||
assertThat(converter.convert(boolFalseConstant), equalTo(BigDecimal.valueOf(0))); | ||
final Boolean boolTrueConstant = true; | ||
assertThat(converter.convert(boolTrueConstant), equalTo(BigDecimal.valueOf(1))); | ||
} | ||
|
||
@Test | ||
void testFloatToBigDecimalConversion() { | ||
BigDecimalConverter converter = new BigDecimalConverter(); | ||
final float fval = 12345.6789f; | ||
assertThat(converter.convert(fval).floatValue(), equalTo(fval)); | ||
} | ||
|
||
@Test | ||
void testBigDecimalToBigDecimalConversion() { | ||
BigDecimalConverter converter = new BigDecimalConverter(); | ||
BigDecimal bigDecimal = new BigDecimal("12345.6789"); | ||
assertThat(converter.convert(bigDecimal), equalTo(bigDecimal)); | ||
} | ||
|
||
@ParameterizedTest | ||
@MethodSource("decimalToBigDecimalValueProvider") | ||
void testDoubleToBigDecimalConversion(BigDecimal expectedBigDecimal, double actualValue, int scale) { | ||
BigDecimalConverter converter = new BigDecimalConverter(); | ||
if(scale!=0) { | ||
converter.setScale(scale); | ||
expectedBigDecimal = expectedBigDecimal.setScale(scale, RoundingMode.HALF_EVEN); | ||
} | ||
assertThat(converter.convert(actualValue), equalTo(expectedBigDecimal)); | ||
} | ||
|
||
private static Stream<Arguments> decimalToBigDecimalValueProvider() { | ||
return Stream.of( | ||
Arguments.of(new BigDecimal ("0.0"), 0, 1), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we add another test case that covers the conversion described in the issue here (#3840) where we can convert There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added additional scenario for this case |
||
Arguments.of(new BigDecimal ("0.0"), 0.0, 1), | ||
Arguments.of(new BigDecimal ("0.00000000000000000000000"), 0.00000000000000000000000, 1), | ||
Arguments.of(BigDecimal.ZERO, BigDecimal.ZERO.doubleValue(), 1), | ||
Arguments.of(new BigDecimal ("1"), (double)1, 1), | ||
Arguments.of(new BigDecimal ("1703908514.045833"), 1703908514.045833, 6), | ||
Arguments.of(new BigDecimal ("1.00000000000000000000000"), 1.00000000000000000000000, 1), | ||
Arguments.of(new BigDecimal ("-12345678912.12345"), -12345678912.12345, 1), | ||
Arguments.of(BigDecimal.ONE, BigDecimal.ONE.doubleValue(), 1), | ||
Arguments.of(new BigDecimal("1.7976931348623157E+308"), 1.7976931348623157E+308, 0), | ||
Arguments.of(BigDecimal.valueOf(Double.MAX_VALUE), Double.MAX_VALUE, 0), | ||
Arguments.of(BigDecimal.valueOf(Double.MIN_VALUE), Double.MIN_VALUE, 0) | ||
); | ||
} | ||
|
||
@Test | ||
void testInvalidBigDecimalConversion() { | ||
BigDecimalConverter converter = new BigDecimalConverter(); | ||
final Map<Object, Object> map = Collections.emptyMap(); | ||
assertThrows(IllegalArgumentException.class, () -> converter.convert(map)); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,7 @@ | |
package org.opensearch.dataprepper.plugins.processor.mutateevent; | ||
|
||
import com.fasterxml.jackson.annotation.JsonProperty; | ||
import org.opensearch.dataprepper.typeconverter.BigDecimalConverter; | ||
|
||
import java.util.List; | ||
import java.util.Optional; | ||
|
@@ -20,6 +21,12 @@ public class ConvertEntryTypeProcessorConfig { | |
@JsonProperty("type") | ||
private TargetType type = TargetType.INTEGER; | ||
|
||
/** | ||
* Optional scale value used only in the case of BigDecimal converter | ||
*/ | ||
@JsonProperty("scale") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we expose this? What would be the value of changing the scale to something else? You could remove the field and keep the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As I listed in the PR description, I thought, we can let the user choose the scale he need per column like
|
||
private int scale = 0; | ||
|
||
@JsonProperty("convert_when") | ||
private String convertWhen; | ||
|
||
|
@@ -36,6 +43,9 @@ public String getKey() { | |
public List<String> getKeys() { return keys; } | ||
|
||
public TargetType getType() { | ||
if(type == TargetType.BIGDECIMAL && scale!=0) { | ||
((BigDecimalConverter) type.getTargetConverter()).setScale(scale); | ||
} | ||
return type; | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we just call this
decimal
?If we keep the big, we should name the enum to
BIG_DECIMAL
. I also think that we should have an underscore in the type name to keep consistency:big_decimal
. This would match field names in OpenSearch likegeo_point
, etc.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Kept the word
BIG
and renamed the references toBIG_DECIMAL
. Both enum and data type name are now modified.