From: Robert Varga Date: Sun, 11 Mar 2018 15:25:40 +0000 (+0100) Subject: Improve EnumerationCodec X-Git-Tag: v14.0.0~1390 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=2b8e60b51ca8b6c5a00d661f4d263c31e8bed9a7;p=yangtools.git Improve EnumerationCodec Now that we have proper information from enumerations, we can use build the codec map as known at generation time and check it against the type we are receiving, adding proper warnings. JIRA: MDSAL-317 Change-Id: Ia5bd3d73e44eba2568818b578bc44985fafb6294 Signed-off-by: Robert Varga --- diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/EnumerationCodec.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/EnumerationCodec.java index ebe9c7d5d5..2e16b0c616 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/EnumerationCodec.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/EnumerationCodec.java @@ -8,58 +8,73 @@ package org.opendaylight.mdsal.binding.dom.codec.impl; import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkState; import static java.util.Objects.requireNonNull; -import com.google.common.collect.BiMap; import com.google.common.collect.ImmutableBiMap; -import com.google.common.collect.ImmutableBiMap.Builder; +import com.google.common.collect.Maps; +import java.util.Arrays; +import java.util.Map; +import java.util.Set; import java.util.concurrent.Callable; import java.util.stream.Collectors; import org.opendaylight.mdsal.binding.dom.codec.impl.ValueTypeCodec.SchemaUnawareCodec; -import org.opendaylight.yangtools.yang.binding.BindingMapping; +import org.opendaylight.yangtools.yang.binding.Enumeration; import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition.EnumPair; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; final class EnumerationCodec extends ReflectionBasedCodec implements SchemaUnawareCodec { - private final ImmutableBiMap> yangValueToBinding; + private static final Logger LOG = LoggerFactory.getLogger(EnumerationCodec.class); - EnumerationCodec(final Class> enumeration, final ImmutableBiMap> schema) { + private final ImmutableBiMap> nameToEnum; + + EnumerationCodec(final Class> enumeration, final Map> nameToEnum) { super(enumeration); - yangValueToBinding = requireNonNull(schema); + this.nameToEnum = ImmutableBiMap.copyOf(nameToEnum); } - static Callable loader(final Class returnType, final EnumTypeDefinition enumSchema) { + static Callable loader(final Class returnType, final EnumTypeDefinition def) { checkArgument(Enum.class.isAssignableFrom(returnType)); - @SuppressWarnings({ "rawtypes", "unchecked" }) - final Class> enumType = (Class) returnType; + @SuppressWarnings("unchecked") + final Class> enumType = (Class>) returnType; return () -> { - final BiMap identifierToYang = BindingMapping.mapEnumAssignedNames( - enumSchema.getValues().stream().map(EnumPair::getName).collect(Collectors.toList())).inverse(); + final Map> mapping = Maps.uniqueIndex(Arrays.asList(enumType.getEnumConstants()), + value -> { + checkArgument(value instanceof Enumeration, + "Enumeration constant %s.%s is not implementing Enumeration", enumType.getName(), value); + return ((Enumeration) value).getName(); + }); - final Builder> builder = ImmutableBiMap.builder(); - for (Enum enumValue : enumType.getEnumConstants()) { - final String yangName = identifierToYang.get(enumValue.name()); - checkState(yangName != null, "Failed to find enumeration constant %s in mapping %s", enumValue, - identifierToYang); - builder.put(yangName, enumValue); + // Check if mapping is a bijection + final Set assignedNames = def.getValues().stream().map(EnumPair::getName) + .collect(Collectors.toSet()); + for (String name : assignedNames) { + if (!mapping.containsKey(name)) { + LOG.warn("Enumeration {} does not contain assigned name '{}' from {}", enumType, name, def); + } + } + for (String name : mapping.keySet()) { + if (!assignedNames.contains(name)) { + LOG.warn("Enumeration {} contains assigned name '{}' not covered by {}", enumType, name, def); + } } - return new EnumerationCodec(enumType, builder.build()); + return new EnumerationCodec(enumType, mapping); }; } @Override - public Object deserialize(final Object input) { - Enum value = yangValueToBinding.get(input); - checkArgument(value != null, "Invalid enumeration value %s. Valid values are %s", input, - yangValueToBinding.keySet()); + public Enum deserialize(final Object input) { + checkArgument(input instanceof String, "Input %s is not a String", input); + final Enum value = nameToEnum.get(input); + checkArgument(value != null, "Invalid enumeration value %s. Valid values are %s", input, nameToEnum.keySet()); return value; } @Override - public Object serialize(final Object input) { - checkArgument(getTypeClass().isInstance(input), "Input must be instance of %s", getTypeClass()); - return yangValueToBinding.inverse().get(input); + public String serialize(final Object input) { + checkArgument(getTypeClass().isInstance(input), "Input %s is not a instance of %s", input, getTypeClass()); + return requireNonNull(nameToEnum.inverse().get(input)); } } \ No newline at end of file diff --git a/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/impl/EnumerationCodecTest.java b/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/impl/EnumerationCodecTest.java index 195cf01f66..9b05d53a54 100644 --- a/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/impl/EnumerationCodecTest.java +++ b/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/impl/EnumerationCodecTest.java @@ -13,13 +13,24 @@ import static org.mockito.Mockito.mock; import com.google.common.collect.ImmutableList; import org.junit.Test; +import org.opendaylight.yangtools.yang.binding.Enumeration; import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition.EnumPair; public class EnumerationCodecTest { - private enum TestEnum { - ENUM + private enum TestEnum implements Enumeration { + ENUM; + + @Override + public String getName() { + return "ENUM"; + } + + @Override + public int getIntValue() { + return 0; + } } @Test