+/*
+ * 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.INT16_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;
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.BinaryTypeDefinition;
import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
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());
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;
}
final TypeDefinitionAwareCodec codec = fromType(typeDefinition);
return (TypeDefinitionAwareCodec<Object, ? extends TypeDefinition<?>>) codec;
}
-
+
public static final <T extends TypeDefinition<T>> TypeDefinitionAwareCodec<?, T> fromType(T typeDefinition) {
T superType = typeDefinition;
while (superType.getBaseType() != null) {
}
} 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;
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>
@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);
}
};
@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);
}
};
@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();
}
};
@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();
}
};
@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();
}
};
@Override
public String serialize(String data) {
- return data.toString();
+ return data == null ? "" : data.toString();
}
};
@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();
}
};
@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();
}
};
@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();
}
};
@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();
}
};
@Override
public String serialize(byte[] data) {
- // FIXME By YANG Spec
- return null;
+ return data == null ? "" : BaseEncoding.base64().encode(data);
}
@Override
public byte[] deserialize(String stringRepresentation) {
- // FIXME By YANG Spec
- return null;
+ return BaseEncoding.base64().decode(stringRepresentation);
}
};
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));
@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);
}
};
@Override
public String serialize(String data) {
- return data.toString();
+ return data == null ? "" : data.toString();
}
};
@Override
public String serialize(BigDecimal data) {
- return data.toString();
+ return data == null ? "" : data.toString();
}
@Override
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;
+ }
+ };
}