Repository: cayenne Updated Branches: refs/heads/master 30a7b5355 -> 756497d02
CAY-2103 cayenne-crypto: support for mapping non-String and non-binary types Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/12d340a5 Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/12d340a5 Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/12d340a5 Branch: refs/heads/master Commit: 12d340a53ee318afe73f79c9b9392ff88cabbf18 Parents: 30a7b53 Author: Andrei Tomashpolskiy <nordman...@gmail.com> Authored: Fri Aug 19 11:39:11 2016 +0300 Committer: Andrei Tomashpolskiy <nordman...@gmail.com> Committed: Fri Aug 19 11:39:11 2016 +0300 ---------------------------------------------------------------------- .../transformer/value/BigDecimalConverter.java | 55 +++++++++++++++++++ .../transformer/value/BigIntegerConverter.java | 31 +++++++++++ .../value/DefaultValueTransformerFactory.java | 6 +++ .../value/BigDecimalConverterTest.java | 56 ++++++++++++++++++++ .../value/BigIntegerConverterTest.java | 32 +++++++++++ 5 files changed, 180 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cayenne/blob/12d340a5/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/value/BigDecimalConverter.java ---------------------------------------------------------------------- diff --git a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/value/BigDecimalConverter.java b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/value/BigDecimalConverter.java new file mode 100644 index 0000000..cd76b4a --- /dev/null +++ b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/value/BigDecimalConverter.java @@ -0,0 +1,55 @@ +package org.apache.cayenne.crypto.transformer.value; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Arrays; + +/** + * Converts between {@link java.math.BigDecimal} and byte[] + * + * @since 4.0 + */ +public class BigDecimalConverter implements BytesConverter<BigDecimal> { + + public static final BytesConverter<BigDecimal> INSTANCE = new BigDecimalConverter(); + + private static final int MIN_BYTES = Integer.BYTES + 1; + + static BigDecimal getBigDecimal(byte[] bytes) { + + byte[] unscaledBytes, scaleBytes; + + if (bytes.length < MIN_BYTES) { + throw new IllegalArgumentException("byte[] is too small for a BigDecimal value: " + bytes.length); + } + + scaleBytes = Arrays.copyOfRange(bytes, 0, Integer.BYTES); + unscaledBytes = Arrays.copyOfRange(bytes, Integer.BYTES, bytes.length); + + return new BigDecimal(new BigInteger(unscaledBytes), IntegerConverter.getInt(scaleBytes)); + } + + static byte[] getBytes(BigDecimal bigDecimal) { + + byte[] result, unscaledBytes, scaleBytes; + + unscaledBytes = bigDecimal.unscaledValue().toByteArray(); + scaleBytes = IntegerConverter.getBytes(bigDecimal.scale()); + + result = new byte[Integer.BYTES + unscaledBytes.length]; + System.arraycopy(scaleBytes, 0, result, Integer.BYTES - scaleBytes.length, scaleBytes.length); + System.arraycopy(unscaledBytes, 0, result, Integer.BYTES, unscaledBytes.length); + + return result; + } + + @Override + public BigDecimal fromBytes(byte[] bytes) { + return getBigDecimal(bytes); + } + + @Override + public byte[] toBytes(BigDecimal value) { + return getBytes(value); + } +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/12d340a5/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/value/BigIntegerConverter.java ---------------------------------------------------------------------- diff --git a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/value/BigIntegerConverter.java b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/value/BigIntegerConverter.java new file mode 100644 index 0000000..3bfa76d --- /dev/null +++ b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/value/BigIntegerConverter.java @@ -0,0 +1,31 @@ +package org.apache.cayenne.crypto.transformer.value; + +import java.math.BigInteger; + +/** + * Converts between {@link java.math.BigInteger} and byte[] + * + * @since 4.0 + */ +public class BigIntegerConverter implements BytesConverter<BigInteger> { + + public static final BytesConverter<BigInteger> INSTANCE = new BigIntegerConverter(); + + static BigInteger getBigInteger(byte[] bytes) { + return new BigInteger(bytes); + } + + static byte[] getBytes(BigInteger bigInt) { + return bigInt.toByteArray(); + } + + @Override + public BigInteger fromBytes(byte[] bytes) { + return getBigInteger(bytes); + } + + @Override + public byte[] toBytes(BigInteger value) { + return getBytes(value); + } +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/12d340a5/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/value/DefaultValueTransformerFactory.java ---------------------------------------------------------------------- diff --git a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/value/DefaultValueTransformerFactory.java b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/value/DefaultValueTransformerFactory.java index 8aa7ea1..c4f2964 100644 --- a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/value/DefaultValueTransformerFactory.java +++ b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/value/DefaultValueTransformerFactory.java @@ -27,6 +27,8 @@ import org.apache.cayenne.map.DbEntity; import org.apache.cayenne.map.ObjAttribute; import org.apache.cayenne.map.ObjEntity; +import java.math.BigDecimal; +import java.math.BigInteger; import java.security.Key; import java.sql.Types; import java.util.Collection; @@ -164,6 +166,8 @@ public class DefaultValueTransformerFactory implements ValueTransformerFactory { map.put(Boolean.class.getName(), BooleanConverter.INSTANCE); map.put(Date.class.getName(), UtilDateConverter.INSTANCE); + map.put(BigInteger.class.getName(), BigIntegerConverter.INSTANCE); + map.put(BigDecimal.class.getName(), BigDecimalConverter.INSTANCE); return map; } @@ -195,6 +199,8 @@ public class DefaultValueTransformerFactory implements ValueTransformerFactory { map.put(Boolean.class.getName(), BooleanConverter.INSTANCE); map.put(Date.class.getName(), UtilDateConverter.INSTANCE); + map.put(BigInteger.class.getName(), BigIntegerConverter.INSTANCE); + map.put(BigDecimal.class.getName(), BigDecimalConverter.INSTANCE); return map; } http://git-wip-us.apache.org/repos/asf/cayenne/blob/12d340a5/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/transformer/value/BigDecimalConverterTest.java ---------------------------------------------------------------------- diff --git a/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/transformer/value/BigDecimalConverterTest.java b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/transformer/value/BigDecimalConverterTest.java new file mode 100644 index 0000000..2d5772a --- /dev/null +++ b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/transformer/value/BigDecimalConverterTest.java @@ -0,0 +1,56 @@ +package org.apache.cayenne.crypto.transformer.value; + +import org.junit.Test; + +import java.math.BigDecimal; +import java.math.BigInteger; + +import static org.junit.Assert.assertEquals; + +public class BigDecimalConverterTest { + + private BigInteger positiveInt = BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.valueOf(Long.MAX_VALUE)); + private BigInteger negativeInt = BigInteger.valueOf(Long.MIN_VALUE).subtract(BigInteger.valueOf(Long.MIN_VALUE)); + + @Test + public void testConverter() { + BigDecimal originalValue = new BigDecimal(positiveInt); + BigDecimalConverter converter = new BigDecimalConverter(); + assertEquals(originalValue, converter.fromBytes(converter.toBytes(originalValue))); + } + + @Test + public void testConverter_Negative() { + BigDecimal originalValue = new BigDecimal(negativeInt); + BigDecimalConverter converter = new BigDecimalConverter(); + assertEquals(originalValue, converter.fromBytes(converter.toBytes(originalValue))); + } + + @Test + public void testConverter_Zero() { + BigDecimal originalValue = BigDecimal.ZERO; + BigDecimalConverter converter = new BigDecimalConverter(); + assertEquals(originalValue, converter.fromBytes(converter.toBytes(originalValue))); + } + + @Test + public void testConverter_Decimal_PositiveScale() { + BigDecimal originalValue = new BigDecimal(negativeInt, Integer.MAX_VALUE / 2); + BigDecimalConverter converter = new BigDecimalConverter(); + assertEquals(originalValue, converter.fromBytes(converter.toBytes(originalValue))); + } + + @Test + public void testConverter_Decimal_NegativeScale() { + BigDecimal originalValue = new BigDecimal(negativeInt, Integer.MIN_VALUE / 2); + BigDecimalConverter converter = new BigDecimalConverter(); + assertEquals(originalValue, converter.fromBytes(converter.toBytes(originalValue))); + } + + @Test + public void testConverter_Decimal_Irrational() { + BigDecimal originalValue = new BigDecimal(Math.sqrt(2)); + BigDecimalConverter converter = new BigDecimalConverter(); + assertEquals(originalValue, converter.fromBytes(converter.toBytes(originalValue))); + } +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/12d340a5/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/transformer/value/BigIntegerConverterTest.java ---------------------------------------------------------------------- diff --git a/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/transformer/value/BigIntegerConverterTest.java b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/transformer/value/BigIntegerConverterTest.java new file mode 100644 index 0000000..3157b41 --- /dev/null +++ b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/transformer/value/BigIntegerConverterTest.java @@ -0,0 +1,32 @@ +package org.apache.cayenne.crypto.transformer.value; + +import org.junit.Test; + +import java.math.BigInteger; + +import static org.junit.Assert.assertEquals; + +public class BigIntegerConverterTest { + + private BigInteger positiveInt = BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.valueOf(Long.MAX_VALUE)); + private BigInteger negativeInt = BigInteger.valueOf(Long.MIN_VALUE).subtract(BigInteger.valueOf(Long.MIN_VALUE)); + + @Test + public void testConverter() { + BigIntegerConverter converter = new BigIntegerConverter(); + assertEquals(positiveInt, converter.fromBytes(converter.toBytes(positiveInt))); + } + + @Test + public void testConverter_Negative() { + BigIntegerConverter converter = new BigIntegerConverter(); + assertEquals(negativeInt, converter.fromBytes(converter.toBytes(negativeInt))); + } + + @Test + public void testConverter_Zero() { + BigInteger originalValue = BigInteger.ZERO; + BigIntegerConverter converter = new BigIntegerConverter(); + assertEquals(originalValue, converter.fromBytes(converter.toBytes(originalValue))); + } +}