Add alternative enum assigned name mapping
[mdsal.git] / binding / mdsal-binding-dom-codec / src / main / java / org / opendaylight / mdsal / binding / dom / codec / impl / EnumerationCodec.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.mdsal.binding.dom.codec.impl;
9
10 import static com.google.common.base.Preconditions.checkArgument;
11 import static com.google.common.base.Preconditions.checkState;
12 import static java.util.Objects.requireNonNull;
13
14 import com.google.common.collect.BiMap;
15 import com.google.common.collect.ImmutableBiMap;
16 import com.google.common.collect.ImmutableBiMap.Builder;
17 import java.util.concurrent.Callable;
18 import java.util.stream.Collectors;
19 import org.opendaylight.mdsal.binding.dom.codec.impl.ValueTypeCodec.SchemaUnawareCodec;
20 import org.opendaylight.yangtools.yang.binding.BindingMapping;
21 import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
22 import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition.EnumPair;
23
24 final class EnumerationCodec extends ReflectionBasedCodec implements SchemaUnawareCodec {
25     private final ImmutableBiMap<String, Enum<?>> yangValueToBinding;
26
27     EnumerationCodec(final Class<? extends Enum<?>> enumeration, final ImmutableBiMap<String, Enum<?>> schema) {
28         super(enumeration);
29         yangValueToBinding = requireNonNull(schema);
30     }
31
32     static Callable<EnumerationCodec> loader(final Class<?> returnType, final EnumTypeDefinition enumSchema) {
33         checkArgument(Enum.class.isAssignableFrom(returnType));
34         @SuppressWarnings({ "rawtypes", "unchecked" })
35         final Class<? extends Enum<?>> enumType = (Class) returnType;
36         return () -> {
37             final BiMap<String, String> identifierToYang = BindingMapping.mapEnumAssignedNames(
38                 enumSchema.getValues().stream().map(EnumPair::getName).collect(Collectors.toList())).inverse();
39
40             final Builder<String, Enum<?>> builder = ImmutableBiMap.builder();
41             for (Enum<?> enumValue : enumType.getEnumConstants()) {
42                 final String yangName = identifierToYang.get(enumValue.name());
43                 checkState(yangName != null, "Failed to find enumeration constant %s in mapping %s", enumValue,
44                         identifierToYang);
45                 builder.put(yangName, enumValue);
46             }
47
48             return new EnumerationCodec(enumType, builder.build());
49         };
50     }
51
52     @Override
53     public Object deserialize(final Object input) {
54         Enum<?> value = yangValueToBinding.get(input);
55         checkArgument(value != null, "Invalid enumeration value %s. Valid values are %s", input,
56                 yangValueToBinding.keySet());
57         return value;
58     }
59
60     @Override
61     public Object serialize(final Object input) {
62         checkArgument(getTypeClass().isInstance(input), "Input must be instance of %s", getTypeClass());
63         return yangValueToBinding.inverse().get(input);
64     }
65 }