[OLINGO-1393]Validate the values for a Decimal data type as per latest spec

This commit is contained in:
ramya vasanth 2019-09-09 10:51:15 +05:30
parent b13071f980
commit 510b213cd6
5 changed files with 168 additions and 16 deletions

View File

@ -1275,7 +1275,7 @@ public class BasicITCase extends AbstractParamTecSvcITCase {
entity.getProperties().add(getFactory().newPrimitiveProperty(PROPERTY_INT64,
getFactory().newPrimitiveValueBuilder().buildInt64(Long.MAX_VALUE)));
entity.getProperties().add(getFactory().newPrimitiveProperty(PROPERTY_DECIMAL,
getFactory().newPrimitiveValueBuilder().buildDecimal(BigDecimal.valueOf(Long.MAX_VALUE))));
getFactory().newPrimitiveValueBuilder().buildDecimal(BigDecimal.valueOf(922337203685477L))));
final ODataEntityUpdateRequest<ClientEntity> requestUpdate = getEdmEnabledClient().getCUDRequestFactory()
.getEntityUpdateRequest(uri, UpdateType.PATCH, entity);
@ -1292,7 +1292,7 @@ public class BasicITCase extends AbstractParamTecSvcITCase {
final ODataRetrieveResponse<ClientEntity> responseGet = requestGet.execute();
assertEquals(Long.MAX_VALUE, responseGet.getBody().getProperty(PROPERTY_INT64).getPrimitiveValue().toValue());
assertEquals(BigDecimal.valueOf(Long.MAX_VALUE), responseGet.getBody().getProperty(PROPERTY_DECIMAL)
assertEquals(BigDecimal.valueOf(922337203685477L), responseGet.getBody().getProperty(PROPERTY_DECIMAL)
.getPrimitiveValue()
.toValue());
}
@ -1395,7 +1395,7 @@ public class BasicITCase extends AbstractParamTecSvcITCase {
.add(getFactory().newPrimitiveProperty(PROPERTY_INT64,
getFactory().newPrimitiveValueBuilder().buildInt64(Long.MIN_VALUE)))
.add(getFactory().newPrimitiveProperty(PROPERTY_DECIMAL,
getFactory().newPrimitiveValueBuilder().buildDecimal(BigDecimal.valueOf(12345678912L))))
getFactory().newPrimitiveValueBuilder().buildDecimal(BigDecimal.valueOf(123456.78912))))
.add(getFactory().newPrimitiveProperty(PROPERTY_INT16,
getFactory().newPrimitiveValueBuilder().buildInt16((short) 2)))));
@ -1413,7 +1413,7 @@ public class BasicITCase extends AbstractParamTecSvcITCase {
final ClientComplexValue complexValue = responseGet.getBody().getComplexValue();
assertEquals(Long.MIN_VALUE, complexValue.get(PROPERTY_INT64).getPrimitiveValue().toValue());
assertEquals(BigDecimal.valueOf(12345678912L), complexValue.get(PROPERTY_DECIMAL).getPrimitiveValue().toValue());
assertEquals(BigDecimal.valueOf(123456.78912), complexValue.get(PROPERTY_DECIMAL).getPrimitiveValue().toValue());
assertEquals(2, complexValue.get(PROPERTY_INT16).getPrimitiveValue().toValue());
}
@ -1428,7 +1428,7 @@ public class BasicITCase extends AbstractParamTecSvcITCase {
final ODataPropertyUpdateRequest requestUpdate = getEdmEnabledClient().getCUDRequestFactory()
.getPropertyPrimitiveValueUpdateRequest(uri,
getFactory().newPrimitiveProperty(PROPERTY_DECIMAL,
getFactory().newPrimitiveValueBuilder().buildInt64(Long.MAX_VALUE)));
getFactory().newPrimitiveValueBuilder().buildInt64(922337203685477L)));
requestUpdate.setContentType(CONTENT_TYPE_JSON_IEEE754_COMPATIBLE);
requestUpdate.setAccept(CONTENT_TYPE_JSON_IEEE754_COMPATIBLE);
@ -1441,7 +1441,7 @@ public class BasicITCase extends AbstractParamTecSvcITCase {
requestGet.setAccept(CONTENT_TYPE_JSON_IEEE754_COMPATIBLE);
final ODataRetrieveResponse<ClientProperty> responseGet = requestGet.execute();
assertEquals(BigDecimal.valueOf(Long.MAX_VALUE), responseGet.getBody().getPrimitiveValue().toValue());
assertEquals(BigDecimal.valueOf(922337203685477L), responseGet.getBody().getPrimitiveValue().toValue());
}
@Test

View File

@ -72,7 +72,7 @@ package org.apache.olingo.commons.api.edm;
public interface EdmPrimitiveType extends EdmType {
String EDM_NAMESPACE = "Edm";
/**
* Checks type compatibility.
*
@ -164,4 +164,20 @@ public interface EdmPrimitiveType extends EdmType {
* @throws EdmPrimitiveTypeException if a required prefix or required surrounding quotation marks are missing
*/
String fromUriLiteral(String literal) throws EdmPrimitiveTypeException;
/**
* Validates literal value for Decimal values in V4.01
*
* @param value the literal value
* @param isNullable whether the <code>null</code> value is allowed
* @param maxLength the maximum length
* @param precision the precision
* @param scale the scale (could be variable or floating)
* @param isUnicode whether non-ASCII characters are allowed (relevant only for Edm.String)
* @return <code>true</code> if the validation is successful
*/
default boolean validateDecimals(String value, Boolean isNullable, Integer maxLength,
Integer precision, String scale, Boolean isUnicode) {
return false;
}
}

View File

@ -83,8 +83,65 @@ public final class EdmDecimal extends SingletonPrimitiveType {
}
final int significantIntegerDigits = "0".equals(matcher.group(1)) ? 0 : matcher.group(1).length();
final int decimals = matcher.group(2) == null ? 0 : matcher.group(2).length();
return (precision == null || precision >= significantIntegerDigits + decimals)
&& (decimals <= (scale == null ? 0 : scale));
return (precision == null || (significantIntegerDigits >= 0 &&
significantIntegerDigits <= precision - ((scale == null) ? 0 : scale))) &&
(decimals >= 0 && decimals <= ((scale == null) ? 0 : scale));
}
@Override
public boolean validateDecimals(final String value,
final Boolean isNullable, final Integer maxLength, final Integer precision,
final String scale, final Boolean isUnicode) {
return value == null
? isNullable == null || isNullable
: validateLiteral(value) && validatePrecisionAndScale(value, precision, scale);
}
private boolean validatePrecisionAndScale(String value, Integer precision, String scale) {
Matcher matcher = PATTERN.matcher(value);
matcher.matches();
if (matcher.group(3) != null) {
String plainValue = new BigDecimal(value).toPlainString();
matcher = PATTERN.matcher(plainValue);
matcher.matches();
}
int significantIntegerDigits = "0".equals(matcher.group(1)) ? 0 : matcher.group(1).length();
int decimals = matcher.group(2) == null ? 0 : matcher.group(2).length();
try {
int scaleValue = (scale == null) ? 0 : Integer.parseInt(scale);
return (precision == null || (significantIntegerDigits >= 0 &&
significantIntegerDigits <= precision - scaleValue)) &&
(decimals >= 0 && decimals <= scaleValue);
} catch(NumberFormatException e) {
String scaleValue = (scale == null) ? String.valueOf(0) : scale;
if (scaleValue.equals("variable")) {
return (precision == null ||
(significantIntegerDigits >= 0 &&
(significantIntegerDigits <= precision - decimals))) &&
(decimals >= 0 && decimals <= ((precision == null) ? 0 : precision));
} else if (scaleValue.equals("floating")) {
Matcher matcher1 = PATTERN.matcher(value);
matcher1.matches();
significantIntegerDigits = "0".equals(matcher1.group(1)) ? 0 : matcher1.group(1).length();
decimals = matcher1.group(2) == null ? 0 : matcher1.group(2).length();
int exponents = 0;
if (matcher1.group(3) != null) {
exponents = Integer.parseInt(matcher1.group(3).substring(1));
if (exponents < -95 || exponents > 96) {
if (String.valueOf(exponents).startsWith("-")) {
significantIntegerDigits += Integer.parseInt(String.valueOf(exponents + 95).substring(1));
exponents = -95;
}
}
return (significantIntegerDigits + decimals) <= 7 && (exponents >= -95 && exponents <= 96);
}
} else {
return false;
}
}
return false;
}
@Override

View File

@ -19,6 +19,7 @@
package org.apache.olingo.commons.core.edm.primitivetype;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.math.BigDecimal;
@ -97,11 +98,10 @@ public class EdmDecimalTest extends PrimitiveTypeBaseTest {
assertEquals(Double.valueOf(0.5), instance.valueOfString("0.5", null, null, 1, 1, null, Double.class));
assertEquals(Float.valueOf(0.5F), instance.valueOfString("0.5", null, null, null, 1, null, Float.class));
assertEquals(new BigDecimal("12.3"), instance.valueOfString("12.3", null, null, 3, 1, null, BigDecimal.class));
assertEquals(new BigDecimal("31991163"), instance.valueOfString("3.1991163E7", null, null, 8, 7,
null, BigDecimal.class));
assertEquals(new BigDecimal("31991163.34"),
instance.valueOfString("3.199116334E7", null, null, 10, 2, null, BigDecimal.class));
expectFacetsErrorInValueOfString(instance, "3.1991163E7", null, 8, 7, null, null);
expectFacetsErrorInValueOfString(instance, "0.5", null, null, null, null, null);
expectFacetsErrorInValueOfString(instance, "-1234", null, null, 2, null, null);
expectFacetsErrorInValueOfString(instance, "1234", null, null, 3, null, null);
@ -110,6 +110,9 @@ public class EdmDecimalTest extends PrimitiveTypeBaseTest {
expectFacetsErrorInValueOfString(instance, "12.34", null, null, 4, 1, null);
expectFacetsErrorInValueOfString(instance, "0.00390625", null, null, 5, null, null);
expectFacetsErrorInValueOfString(instance, "0.00390625", null, null, null, 7, null);
expectFacetsErrorInValueOfString(instance, "-129", null, null, Integer.MAX_VALUE, Integer.MAX_VALUE, null);
expectFacetsErrorInValueOfString(instance, "-32769", null, null, Integer.MAX_VALUE, Integer.MAX_VALUE, null);
expectFacetsErrorInValueOfString(instance, "32768", null, null, Integer.MAX_VALUE, Integer.MAX_VALUE, null);
expectContentErrorInValueOfString(instance, "1.");
expectContentErrorInValueOfString(instance, ".1");
@ -117,10 +120,6 @@ public class EdmDecimalTest extends PrimitiveTypeBaseTest {
expectContentErrorInValueOfString(instance, "1M");
expectContentErrorInValueOfString(instance, "0x42");
expectUnconvertibleErrorInValueOfString(instance, "-129", Byte.class);
expectUnconvertibleErrorInValueOfString(instance, "128", Byte.class);
expectUnconvertibleErrorInValueOfString(instance, "-32769", Short.class);
expectUnconvertibleErrorInValueOfString(instance, "32768", Short.class);
expectUnconvertibleErrorInValueOfString(instance, "-2147483649", Integer.class);
expectUnconvertibleErrorInValueOfString(instance, "2147483648", Integer.class);
expectUnconvertibleErrorInValueOfString(instance, "-9223372036854775809", Long.class);
@ -130,4 +129,84 @@ public class EdmDecimalTest extends PrimitiveTypeBaseTest {
expectTypeErrorInValueOfString(instance, "1");
}
@Test
public void validateDecimal() throws Exception {
assertFalse(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal).
validate("3.1991163E7", null, null, 8, 7, null));
assertTrue(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal).
validate("1", null, null, null, null, null));
assertFalse(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal).
validate("1.2", null, null, null, 0, null));
assertFalse(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal).
validate("10.2", false, null, 3, 2, null));
assertTrue(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal).
validate("1.2", false, null, 3, 2, null));
assertTrue(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal).
validate("0.12", false, null, 3, 2, null));
assertTrue(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal).
validate("1.23", false, null, 3, 2, null));
assertTrue(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal).
validate("1.03", false, null, 3, 2, null));
assertFalse(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal).
validate("1.03", false, null, 3, null, null));
assertTrue(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal).
validate("12", false, null, 3, null, null));
assertTrue(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal).
validate("12", false, null, null, 2, null));
assertTrue(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal).
validate("0.12", false, null, null, 2, null));
assertTrue(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal).
validate("12", false, null, null, null, null));
assertFalse(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal).
validate("0.12", false, null, null, null, null));
assertTrue(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal).
validate("0.23", false, null, 2, 2, null));
assertTrue(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal).
validate("0.7", false, null, 2, 2, null));
assertFalse(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal).
validate("12e-101", false, null, 2, 2, null));
assertFalse(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal).
validate("12e101", false, null, 2, 2, null));
assertTrue(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal).
validate("-1.234567e3", false, null, 7, 3, null));
assertFalse(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal).
validate("0.7", false, null, 2, 3, null));
}
@Test
public void validateDecimalInV401() throws Exception {
assertTrue(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal).
validateDecimals("0.123", null, null, 3, "variable", null));
assertTrue(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal).
validateDecimals("1.23", null, null, 3, "variable", null));
assertTrue(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal).
validateDecimals("0.23", null, null, 3, "variable", null));
assertTrue(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal).
validateDecimals("0.7", null, null, 3, "variable", null));
assertTrue(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal).
validateDecimals("123", null, null, 3, "variable", null));
assertTrue(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal).
validateDecimals("12.3", null, null, 3, "variable", null));
assertFalse(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal).
validateDecimals("12.34", null, null, 3, "variable", null));
assertFalse(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal).
validateDecimals("1234", null, null, 3, "variable", null));
assertFalse(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal).
validateDecimals("123.4", null, null, 3, "variable", null));
assertFalse(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal).
validateDecimals("123.4", null, null, null, "variable", null));
assertTrue(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal).
validateDecimals("-1.234567e3", null, null, 7, "floating", null));
assertTrue(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal).
validateDecimals("1e-101", null, null, 7, "floating", null));
assertTrue(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal).
validateDecimals("9.999999e96", null, null, 7, "floating", null));
assertFalse(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal).
validateDecimals("1e-102", null, null, 7, "floating", null));
assertFalse(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal).
validateDecimals("1e97", null, null, 7, "floating", null));
}
}

View File

@ -85,7 +85,7 @@ public abstract class PrimitiveTypeBaseTest {
protected void expectUnconvertibleErrorInValueOfString(final EdmPrimitiveType instance, final String value,
final Class<?> type) {
expectErrorInValueOfString(instance, value, true, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, true,
expectErrorInValueOfString(instance, value, true, Integer.MAX_VALUE, Integer.MAX_VALUE, null, true,
type, "cannot be converted to");
}