From 8321abdf1c19fca2f99311631c05ea1c8206c80f Mon Sep 17 00:00:00 2001 From: Lukas Sedlak Date: Sat, 25 Jan 2014 12:52:08 +0100 Subject: [PATCH] Fix for Bug 274. Added implementation into TypeDefinitionAwareCodec for handling of Integer values in different formats. Added support for Hexadecimal, Octal and Integer numbers. Hexadecimal numbers MUST be in format starting with 0x or 0X and following by rest of hexadecimal digits. The octal numbers MUST start with "0". All of Integer numbers can start with optional "+" or "-" sign. Signed-off-by: Lukas Sedlak --- .../impl/codec/TypeDefinitionAwareCodec.java | 107 +++++++++++++-- .../impl/test/codecs/IntCodecStringTest.java | 129 ++++++++++++++++++ 2 files changed, 224 insertions(+), 12 deletions(-) create mode 100644 yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/test/codecs/IntCodecStringTest.java diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/TypeDefinitionAwareCodec.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/TypeDefinitionAwareCodec.java index 4d7f80f099..e5a1b584e1 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/TypeDefinitionAwareCodec.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/TypeDefinitionAwareCodec.java @@ -19,6 +19,8 @@ import static org.opendaylight.yangtools.yang.model.util.BaseTypes.UINT8_QNAME; import java.math.BigDecimal; import java.math.BigInteger; import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.opendaylight.yangtools.yang.data.api.codec.BinaryCodec; import org.opendaylight.yangtools.yang.data.api.codec.BitsCodec; @@ -56,10 +58,60 @@ import com.google.common.collect.ImmutableSet; import com.google.common.io.BaseEncoding; public abstract class TypeDefinitionAwareCodec> implements DataStringCodec { - + + private static final Pattern intPattern = Pattern.compile("[+-]?[1-9][0-9]*$"); + private static final Pattern hexPattern = Pattern.compile("[+-]?0[xX][0-9a-fA-F]+"); + private static final Pattern octalPattern = Pattern.compile("[+-]?0[1-7][0-7]*$"); + private final Optional typeDefinition; private final Class inputClass; - + + private static final int provideBase(final String integer) { + if (integer == null) { + throw new IllegalArgumentException("String representing integer number cannot be NULL!"); + } + + if ((integer.length() == 1) && (integer.charAt(0) == '0')) { + return 10; + } + + final Matcher intMatcher = intPattern.matcher(integer); + if (intMatcher.matches()) { + return 10; + } else { + final Matcher hexMatcher = hexPattern.matcher(integer); + if (hexMatcher.matches()) { + return 16; + } else { + final Matcher octMatcher = octalPattern.matcher(integer); + if (octMatcher.matches()) { + return 8; + } else { + throw new NumberFormatException("Incorrect lexical representation of Integer value!" + + "The Integer value can be defined as Integer Number, Hexadecimal Number or" + + "Octal Number. The sign vlues are allowed. " + + "Spaces between digits are NOT allowed!"); + } + } + } + } + + private static String normalizeHexadecimal(final String hexInt) { + if (hexInt == null) { + throw new IllegalArgumentException( + "String representing integer number in Hexadecimal format cannot be NULL!"); + } + final String normalizedString; + if (hexInt.contains("x")) { + normalizedString = hexInt.replace("x", ""); + } else if (hexInt.contains("X")) { + normalizedString = hexInt.replace("X", ""); + } else { + normalizedString = hexInt; + } + return normalizedString; + } + public static final BinaryCodecStringImpl BINARY_DEFAULT_CODEC = new BinaryCodecStringImpl( Optional. absent()); @@ -196,7 +248,7 @@ public abstract class TypeDefinitionAwareCodec> i @Override public Boolean deserialize(String stringRepresentation) { - return Boolean.parseBoolean(stringRepresentation); + return Boolean.valueOf(stringRepresentation); } }; @@ -214,7 +266,11 @@ public abstract class TypeDefinitionAwareCodec> i @Override public Short deserialize(String stringRepresentation) { - return Short.parseShort(stringRepresentation); + int base = provideBase(stringRepresentation); + if (base == 16) { + return Short.valueOf(normalizeHexadecimal(stringRepresentation), base); + } + return Short.valueOf(stringRepresentation, base); } }; @@ -226,7 +282,11 @@ public abstract class TypeDefinitionAwareCodec> i @Override public Integer deserialize(String stringRepresentation) { - return Integer.parseInt(stringRepresentation); + int base = provideBase(stringRepresentation); + if (base == 16) { + return Integer.valueOf(normalizeHexadecimal(stringRepresentation), base); + } + return Integer.valueOf(stringRepresentation, base); } @Override @@ -244,7 +304,11 @@ public abstract class TypeDefinitionAwareCodec> i @Override public Long deserialize(String stringRepresentation) { - return Long.parseLong(stringRepresentation); + int base = provideBase(stringRepresentation); + if (base == 16) { + return Long.valueOf(normalizeHexadecimal(stringRepresentation), base); + } + return Long.valueOf(stringRepresentation, base); } @Override @@ -262,8 +326,11 @@ public abstract class TypeDefinitionAwareCodec> i @Override public BigInteger deserialize(String stringRepresentation) { - // FIXME: Implement codec correctly - return BigInteger.valueOf(Long.valueOf(stringRepresentation)); + int base = provideBase(stringRepresentation); + if (base == 16) { + return new BigInteger(normalizeHexadecimal(stringRepresentation), base); + } + return new BigInteger(stringRepresentation, base); } @Override @@ -299,7 +366,11 @@ public abstract class TypeDefinitionAwareCodec> i @Override public Short deserialize(String stringRepresentation) { - return Short.valueOf(stringRepresentation); + int base = provideBase(stringRepresentation); + if (base == 16) { + return Short.valueOf(normalizeHexadecimal(stringRepresentation), base); + } + return Short.valueOf(stringRepresentation, base); } @Override @@ -317,7 +388,11 @@ public abstract class TypeDefinitionAwareCodec> i @Override public Integer deserialize(String stringRepresentation) { - return Integer.valueOf(stringRepresentation); + int base = provideBase(stringRepresentation); + if (base == 16) { + return Integer.valueOf(normalizeHexadecimal(stringRepresentation), base); + } + return Integer.valueOf(stringRepresentation, base); } @Override @@ -335,7 +410,11 @@ public abstract class TypeDefinitionAwareCodec> i @Override public Long deserialize(String stringRepresentation) { - return Long.parseLong(stringRepresentation); + int base = provideBase(stringRepresentation); + if (base == 16) { + return Long.valueOf(normalizeHexadecimal(stringRepresentation), base); + } + return Long.valueOf(stringRepresentation, base); } @Override @@ -353,7 +432,11 @@ public abstract class TypeDefinitionAwareCodec> i @Override public Byte deserialize(String stringRepresentation) { - return Byte.parseByte(stringRepresentation); + int base = provideBase(stringRepresentation); + if (base == 16) { + return Byte.valueOf(normalizeHexadecimal(stringRepresentation), base); + } + return Byte.valueOf(stringRepresentation, base); } @Override diff --git a/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/test/codecs/IntCodecStringTest.java b/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/test/codecs/IntCodecStringTest.java new file mode 100644 index 0000000000..4d641b8055 --- /dev/null +++ b/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/test/codecs/IntCodecStringTest.java @@ -0,0 +1,129 @@ +package org.opendaylight.yangtools.yang.data.impl.test.codecs; + +import static org.junit.Assert.assertEquals; + +import java.math.BigInteger; + +import org.junit.Test; +import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec; + +public class IntCodecStringTest { + + @Test + public void uint8CodecTest() { + final String hexa = "0x40"; + final String octal = "0100"; + final String integer = "64"; + + assertEquals(TypeDefinitionAwareCodec.UINT8_DEFAULT_CODEC.deserialize(hexa), Short.valueOf("040", 16)); + assertEquals(TypeDefinitionAwareCodec.UINT8_DEFAULT_CODEC.deserialize(octal), Short.valueOf(octal, 8)); + assertEquals(TypeDefinitionAwareCodec.UINT8_DEFAULT_CODEC.deserialize(integer), Short.valueOf(integer, 10)); + assertEquals(TypeDefinitionAwareCodec.UINT8_DEFAULT_CODEC.deserialize("0"), Short.valueOf("0", 10)); + } + + @Test + public void uint16CodecTest() { + final String hexa = "0X45c"; + final String octal = "02134"; + final String integer = "1116"; + + assertEquals(TypeDefinitionAwareCodec.UINT16_DEFAULT_CODEC.deserialize(hexa), Integer.valueOf("045c", 16)); + assertEquals(TypeDefinitionAwareCodec.UINT16_DEFAULT_CODEC.deserialize(octal), Integer.valueOf(octal, 8)); + assertEquals(TypeDefinitionAwareCodec.UINT16_DEFAULT_CODEC.deserialize(integer), Integer.valueOf(integer, 10)); + } + + @Test + public void uint32CodecTest() { + final String hexa = "0x45FFFCDE"; + final String octal = "010577776336"; + final String integer = "1174404318"; + + assertEquals(TypeDefinitionAwareCodec.UINT32_DEFAULT_CODEC.deserialize(hexa), Long.valueOf("45FFFCDE", 16)); + assertEquals(TypeDefinitionAwareCodec.UINT32_DEFAULT_CODEC.deserialize(octal), Long.valueOf(octal, 8)); + assertEquals(TypeDefinitionAwareCodec.UINT32_DEFAULT_CODEC.deserialize(integer), Long.valueOf(integer, 10)); + } + + @Test + public void uint64CodecTest() { + final String hexa = "0X75EDC78edCBA"; + final String octal = "03536670743556272"; + final String integer = "129664115727546"; + + assertEquals(TypeDefinitionAwareCodec.UINT64_DEFAULT_CODEC.deserialize(hexa), + new BigInteger("75EDC78edCBA", 16)); + assertEquals(TypeDefinitionAwareCodec.UINT64_DEFAULT_CODEC.deserialize(octal), new BigInteger(octal, 8)); + assertEquals(TypeDefinitionAwareCodec.UINT64_DEFAULT_CODEC.deserialize(integer), new BigInteger(integer, 10)); + } + + @Test + public void int8CodecTest() { + final String hexa = "0x40"; + final String negHexa = "-0x40"; + final String octal = "+0100"; + final String negOctal = "-0100"; + final String integer = "64"; + final String negInteger = "-64"; + + assertEquals(TypeDefinitionAwareCodec.INT8_DEFAULT_CODEC.deserialize(hexa), Byte.valueOf("040", 16)); + assertEquals(TypeDefinitionAwareCodec.INT8_DEFAULT_CODEC.deserialize(negHexa), Byte.valueOf("-040", 16)); + assertEquals(TypeDefinitionAwareCodec.INT8_DEFAULT_CODEC.deserialize(octal), Byte.valueOf(octal, 8)); + assertEquals(TypeDefinitionAwareCodec.INT8_DEFAULT_CODEC.deserialize(negOctal), Byte.valueOf(negOctal, 8)); + assertEquals(TypeDefinitionAwareCodec.INT8_DEFAULT_CODEC.deserialize(integer), Byte.valueOf(integer, 10)); + assertEquals(TypeDefinitionAwareCodec.INT8_DEFAULT_CODEC.deserialize(negInteger), Byte.valueOf(negInteger, 10)); + } + + @Test + public void int16CodecTest() { + final String hexa = "+0X45c"; + final String negHexa = "-0X45c"; + final String octal = "02134"; + final String negOctal = "-02134"; + final String integer = "+1116"; + final String negInteger = "-1116"; + + assertEquals(TypeDefinitionAwareCodec.INT16_DEFAULT_CODEC.deserialize(hexa), Short.valueOf("+045c", 16)); + assertEquals(TypeDefinitionAwareCodec.INT16_DEFAULT_CODEC.deserialize(negHexa), Short.valueOf("-045c", 16)); + assertEquals(TypeDefinitionAwareCodec.INT16_DEFAULT_CODEC.deserialize(octal), Short.valueOf(octal, 8)); + assertEquals(TypeDefinitionAwareCodec.INT16_DEFAULT_CODEC.deserialize(negOctal), Short.valueOf(negOctal, 8)); + assertEquals(TypeDefinitionAwareCodec.INT16_DEFAULT_CODEC.deserialize(integer), Short.valueOf(integer, 10)); + assertEquals(TypeDefinitionAwareCodec.INT16_DEFAULT_CODEC.deserialize(negInteger), + Short.valueOf(negInteger, 10)); + } + + @Test + public void int32CodecTest() { + final String hexa = "0x45FFFCDE"; + final String negHexa = "-0x45FFFCDE"; + final String octal = "010577776336"; + final String negOctal = "-010577776336"; + final String integer = "1174404318"; + final String negInteger = "-1174404318"; + + assertEquals(TypeDefinitionAwareCodec.INT32_DEFAULT_CODEC.deserialize(hexa), Integer.valueOf("+045FFFCDE", 16)); + assertEquals(TypeDefinitionAwareCodec.INT32_DEFAULT_CODEC.deserialize(negHexa), + Integer.valueOf("-045FFFCDE", 16)); + assertEquals(TypeDefinitionAwareCodec.INT32_DEFAULT_CODEC.deserialize(octal), Integer.valueOf(octal, 8)); + assertEquals(TypeDefinitionAwareCodec.INT32_DEFAULT_CODEC.deserialize(negOctal), Integer.valueOf(negOctal, 8)); + assertEquals(TypeDefinitionAwareCodec.INT32_DEFAULT_CODEC.deserialize(integer), Integer.valueOf(integer, 10)); + assertEquals(TypeDefinitionAwareCodec.INT32_DEFAULT_CODEC.deserialize(negInteger), + Integer.valueOf(negInteger, 10)); + } + + @Test + public void int64CodecTest() { + final String hexa = "0X75EDC78edCBA"; + final String negHexa = "-0X75EDC78edCBA"; + final String octal = "+03536670743556272"; + final String negOctal = "-03536670743556272"; + final String integer = "+129664115727546"; + final String negInteger = "-129664115727546"; + + assertEquals(TypeDefinitionAwareCodec.INT64_DEFAULT_CODEC.deserialize(hexa), Long.valueOf("075EDC78edCBA", 16)); + assertEquals(TypeDefinitionAwareCodec.INT64_DEFAULT_CODEC.deserialize(negHexa), + Long.valueOf("-075EDC78edCBA", 16)); + assertEquals(TypeDefinitionAwareCodec.INT64_DEFAULT_CODEC.deserialize(octal), Long.valueOf(octal, 8)); + assertEquals(TypeDefinitionAwareCodec.INT64_DEFAULT_CODEC.deserialize(negOctal), Long.valueOf(negOctal, 8)); + assertEquals(TypeDefinitionAwareCodec.INT64_DEFAULT_CODEC.deserialize(integer), Long.valueOf(integer, 10)); + assertEquals(TypeDefinitionAwareCodec.INT64_DEFAULT_CODEC.deserialize(negInteger), Long.valueOf(negInteger, 10)); + } +} -- 2.36.6