[OLINGO-1393]Validate the values for a Decimal data type as per latest spec
This commit is contained in:
parent
b13071f980
commit
510b213cd6
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue