Resolved problem - schema node was not found for XML translation
[yangtools.git] / yang / yang-data-impl / src / main / java / org / opendaylight / yangtools / yang / data / impl / codec / TypeDefinitionAwareCodec.java
index 31a23b509c56442daa25be86b15dab384a4069ef..a1fa857775319ca249d50484604bf22d16703b23 100644 (file)
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
 package org.opendaylight.yangtools.yang.data.impl.codec;
 
-import static org.opendaylight.yangtools.yang.model.util.BaseTypes.*;
+import static org.opendaylight.yangtools.yang.model.util.BaseTypes.INT16_QNAME;
+import static org.opendaylight.yangtools.yang.model.util.BaseTypes.INT32_QNAME;
+import static org.opendaylight.yangtools.yang.model.util.BaseTypes.INT64_QNAME;
+import static org.opendaylight.yangtools.yang.model.util.BaseTypes.INT8_QNAME;
+import static org.opendaylight.yangtools.yang.model.util.BaseTypes.UINT16_QNAME;
+import static org.opendaylight.yangtools.yang.model.util.BaseTypes.UINT32_QNAME;
+import static org.opendaylight.yangtools.yang.model.util.BaseTypes.UINT64_QNAME;
+import static org.opendaylight.yangtools.yang.model.util.BaseTypes.UINT8_QNAME;
 
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.util.Set;
-
-import javax.xml.bind.DatatypeConverter;
-
-import org.opendaylight.yangtools.yang.data.api.codec.*;
+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;
+import org.opendaylight.yangtools.yang.data.api.codec.BooleanCodec;
+import org.opendaylight.yangtools.yang.data.api.codec.DecimalCodec;
+import org.opendaylight.yangtools.yang.data.api.codec.EmptyCodec;
+import org.opendaylight.yangtools.yang.data.api.codec.EnumCodec;
+import org.opendaylight.yangtools.yang.data.api.codec.Int16Codec;
+import org.opendaylight.yangtools.yang.data.api.codec.Int32Codec;
+import org.opendaylight.yangtools.yang.data.api.codec.Int64Codec;
+import org.opendaylight.yangtools.yang.data.api.codec.Int8Codec;
+import org.opendaylight.yangtools.yang.data.api.codec.StringCodec;
+import org.opendaylight.yangtools.yang.data.api.codec.Uint16Codec;
+import org.opendaylight.yangtools.yang.data.api.codec.Uint32Codec;
+import org.opendaylight.yangtools.yang.data.api.codec.Uint64Codec;
+import org.opendaylight.yangtools.yang.data.api.codec.Uint8Codec;
+import org.opendaylight.yangtools.yang.data.api.codec.UnionCodec;
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.type.*;
-
-import com.google.common.base.*;
+import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.BooleanTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.EmptyTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Splitter;
 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());
 
@@ -66,6 +157,9 @@ public abstract class TypeDefinitionAwareCodec<J, T extends TypeDefinition<T>> i
     public static final Uint64CodecStringImpl UINT64_DEFAULT_CODEC = new Uint64CodecStringImpl(
             Optional.<UnsignedIntegerTypeDefinition> absent());
 
+    public static final UnionCodecStringImpl UNION_DEFAULT_CODEC = new UnionCodecStringImpl(
+            Optional.<UnionTypeDefinition> absent());
+
     public Class<J> getInputClass() {
         return inputClass;
     }
@@ -119,6 +213,8 @@ public abstract class TypeDefinitionAwareCodec<J, T extends TypeDefinition<T>> i
             }
         } else if (superType instanceof StringTypeDefinition) {
             codec = STRING_DEFAULT_CODEC;
+        } else if (superType instanceof UnionTypeDefinition) {
+            codec = UNION_DEFAULT_CODEC;
         } else if (superType instanceof UnsignedIntegerTypeDefinition) {
             if (UINT8_QNAME.equals(superType.getQName())) {
                 codec = UINT8_DEFAULT_CODEC;
@@ -133,7 +229,9 @@ public abstract class TypeDefinitionAwareCodec<J, T extends TypeDefinition<T>> i
                 codec = UINT64_DEFAULT_CODEC;
             }
         }
-        return (TypeDefinitionAwareCodec<?, T>) codec;
+        @SuppressWarnings("unchecked")
+        TypeDefinitionAwareCodec<?, T> ret = (TypeDefinitionAwareCodec<?, T>) codec;
+        return ret;
     }
 
     public static class BooleanCodecStringImpl extends TypeDefinitionAwareCodec<Boolean, BooleanTypeDefinition>
@@ -145,12 +243,12 @@ public abstract class TypeDefinitionAwareCodec<J, T extends TypeDefinition<T>> i
 
         @Override
         public String serialize(Boolean data) {
-            return data.toString();
+            return data == null ? "" : data.toString();
         }
 
         @Override
         public Boolean deserialize(String stringRepresentation) {
-            return Boolean.parseBoolean(stringRepresentation);
+            return Boolean.valueOf(stringRepresentation);
         }
     };
 
@@ -163,12 +261,16 @@ public abstract class TypeDefinitionAwareCodec<J, T extends TypeDefinition<T>> i
 
         @Override
         public String serialize(Short data) {
-            return data.toString();
+            return data == null ? "" : data.toString();
         }
 
         @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);
         }
     };
 
@@ -180,12 +282,16 @@ 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
         public String serialize(Integer data) {
-            return data.toString();
+            return data == null ? "" : data.toString();
         }
     };
 
@@ -198,12 +304,16 @@ 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
         public String serialize(Long data) {
-            return data.toString();
+            return data == null ? "" : data.toString();
         }
     };
 
@@ -216,13 +326,16 @@ 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
         public String serialize(BigInteger data) {
-            return data.toString();
+            return data == null ? "" : data.toString();
         }
     };
 
@@ -240,7 +353,7 @@ public abstract class TypeDefinitionAwareCodec<J, T extends TypeDefinition<T>> i
 
         @Override
         public String serialize(String data) {
-            return data.toString();
+            return data == null ? "" : data.toString();
         }
     };
 
@@ -253,12 +366,16 @@ 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
         public String serialize(Short data) {
-            return data.toString();
+            return data == null ? "" : data.toString();
         }
     };
 
@@ -271,12 +388,16 @@ 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
         public String serialize(Integer data) {
-            return data.toString();
+            return data == null ? "" : data.toString();
         }
     };
 
@@ -289,12 +410,16 @@ 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
         public String serialize(Long data) {
-            return data.toString();
+            return data == null ? "" : data.toString();
         }
     };
 
@@ -307,12 +432,16 @@ 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
         public String serialize(Byte data) {
-            return data.toString();
+            return data == null ? "" : data.toString();
         }
     };
 
@@ -343,7 +472,7 @@ public abstract class TypeDefinitionAwareCodec<J, T extends TypeDefinition<T>> i
 
         @Override
         public String serialize(byte[] data) {
-            return BaseEncoding.base64().encode(data);
+            return data == null ? "" : BaseEncoding.base64().encode(data);
         }
 
         @Override
@@ -355,6 +484,9 @@ public abstract class TypeDefinitionAwareCodec<J, T extends TypeDefinition<T>> i
     public static final class BitsCodecStringImpl extends TypeDefinitionAwareCodec<Set<String>, BitsTypeDefinition>
             implements BitsCodec<String> {
 
+        public static final Joiner JOINER = Joiner.on(" ").skipNulls();
+        public static final Splitter SPLITTER = Splitter.on(' ').omitEmptyStrings().trimResults();
+
         @SuppressWarnings("unchecked")
         protected BitsCodecStringImpl(Optional<BitsTypeDefinition> typeDef) {
             super(typeDef, (Class<Set<String>>) ((Class<?>) Set.class));
@@ -362,12 +494,14 @@ public abstract class TypeDefinitionAwareCodec<J, T extends TypeDefinition<T>> i
 
         @Override
         public String serialize(Set<String> data) {
-            return Joiner.on(" ").join(data).toString();
+            return data == null ? "" : JOINER.join(data);
         }
 
         @Override
         public Set<String> deserialize(String stringRepresentation) {
-            String[] strings = stringRepresentation.split(" ");
+            if (stringRepresentation == null)
+                return ImmutableSet.of();
+            Iterable<String> strings = SPLITTER.split(stringRepresentation);
             return ImmutableSet.copyOf(strings);
         }
     };
@@ -386,7 +520,7 @@ public abstract class TypeDefinitionAwareCodec<J, T extends TypeDefinition<T>> i
 
         @Override
         public String serialize(String data) {
-            return data.toString();
+            return data == null ? "" : data.toString();
         }
     };
 
@@ -399,7 +533,7 @@ public abstract class TypeDefinitionAwareCodec<J, T extends TypeDefinition<T>> i
 
         @Override
         public String serialize(BigDecimal data) {
-            return data.toString();
+            return data == null ? "" : data.toString();
         }
 
         @Override
@@ -407,4 +541,22 @@ public abstract class TypeDefinitionAwareCodec<J, T extends TypeDefinition<T>> i
             return new BigDecimal(stringRepresentation);
         }
     };
+
+    public static class UnionCodecStringImpl extends TypeDefinitionAwareCodec<String, UnionTypeDefinition> implements
+            UnionCodec<String> {
+
+        protected UnionCodecStringImpl(Optional<UnionTypeDefinition> typeDef) {
+            super(typeDef, String.class);
+        }
+
+        @Override
+        public String serialize(String data) {
+            return data == null ? "" : data;
+        }
+
+        @Override
+        public String deserialize(String stringRepresentation) {
+            return stringRepresentation;
+        }
+    };
 }