Fix for Bug 274. 64/4764/1
authorLukas Sedlak <lsedlak@cisco.com>
Sat, 25 Jan 2014 11:52:08 +0000 (12:52 +0100)
committerLukas Sedlak <lsedlak@cisco.com>
Sat, 25 Jan 2014 11:52:08 +0000 (12:52 +0100)
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 <lsedlak@cisco.com>
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/TypeDefinitionAwareCodec.java
yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/test/codecs/IntCodecStringTest.java [new file with mode: 0644]

index 4d7f80f099553fe0513c6083307f65757bbbb0c2..e5a1b584e15d7da90cad171441fb12687e4ee258 100644 (file)
@@ -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<J, T extends TypeDefinition<T>> implements DataStringCodec<J> {
-
+    
+    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<T> typeDefinition;
     private final Class<J> 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.<BinaryTypeDefinition> absent());
 
@@ -196,7 +248,7 @@ public abstract class TypeDefinitionAwareCodec<J, T extends TypeDefinition<T>> i
 
         @Override
         public Boolean deserialize(String stringRepresentation) {
-            return Boolean.parseBoolean(stringRepresentation);
+            return Boolean.valueOf(stringRepresentation);
         }
     };
 
@@ -214,7 +266,11 @@ public abstract class TypeDefinitionAwareCodec<J, T extends TypeDefinition<T>> 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<J, T extends TypeDefinition<T>> 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<J, T extends TypeDefinition<T>> 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<J, T extends TypeDefinition<T>> 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<J, T extends TypeDefinition<T>> 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<J, T extends TypeDefinition<T>> 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<J, T extends TypeDefinition<T>> 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<J, T extends TypeDefinition<T>> 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 (file)
index 0000000..4d641b8
--- /dev/null
@@ -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));
+    }
+}