From: Robert Varga Date: Mon, 5 Sep 2016 14:41:37 +0000 (+0200) Subject: BUG-5561: retain SchemaContext order for bits X-Git-Tag: release/boron-sr1~4 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=mdsal.git;a=commitdiff_plain;h=efc5fff4e5e7a52821bb44eb6f8cdab772897024 BUG-5561: retain SchemaContext order for bits This patch reworks BitsCodec so it retains the bit order defined in SchemaContext, which by extension means the values coming from Binding objects should end up being sorted by position. Change-Id: Ice154dd7e38e6b213c281ddb492408f619e3a5f8 Signed-off-by: Robert Varga (cherry picked from commit 85945172d532b22797b0f1786dbf448c63b66f63) --- diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/BitsCodec.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/BitsCodec.java index 38e3e3a04e..fa1b5263b9 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/BitsCodec.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/BitsCodec.java @@ -8,19 +8,21 @@ package org.opendaylight.yangtools.binding.data.codec.impl; import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableSortedMap; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.util.HashSet; +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedHashMap; import java.util.Map; import java.util.Map.Entry; import java.util.Set; -import java.util.SortedMap; -import java.util.TreeMap; +import java.util.TreeSet; import java.util.concurrent.Callable; import org.opendaylight.yangtools.binding.data.codec.impl.ValueTypeCodec.SchemaUnawareCodec; import org.opendaylight.yangtools.yang.binding.BindingMapping; @@ -29,22 +31,30 @@ import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition.Bit; final class BitsCodec extends ReflectionBasedCodec implements SchemaUnawareCodec { private static final MethodType CONSTRUCTOR_INVOKE_TYPE = MethodType.methodType(Object.class, Boolean[].class); - private final Map valueGetters; - private final MethodHandle constructor; - private BitsCodec(final Class typeClass, final SortedMap valueGetters, - final MethodHandle constructor) { + // Ordered by position + private final Map getters; + // Ordered by lexical name + private final Set ctorArgs; + private final MethodHandle ctor; + + private BitsCodec(final Class typeClass, final MethodHandle ctor, final Set ctorArgs, + final Map getters) { super(typeClass); - this.valueGetters = ImmutableSortedMap.copyOf(valueGetters); - this.constructor = Preconditions.checkNotNull(constructor); + this.ctor = Preconditions.checkNotNull(ctor); + this.ctorArgs = ImmutableSet.copyOf(ctorArgs); + this.getters = ImmutableMap.copyOf(getters); } static Callable loader(final Class returnType, final BitsTypeDefinition rootType) { return () -> { - final SortedMap valueGetters = new TreeMap<>(); + final Map getters = new LinkedHashMap<>(); + final Set ctorArgs = new TreeSet<>(); + for (Bit bit : rootType.getBits()) { final Method valueGetter = returnType.getMethod("is" + BindingMapping.getClassName(bit.getName())); - valueGetters.put(bit.getName(), valueGetter); + ctorArgs.add(bit.getName()); + getters.put(bit.getName(), valueGetter); } Constructor constructor = null; for (Constructor cst : returnType.getConstructors()) { @@ -54,8 +64,8 @@ final class BitsCodec extends ReflectionBasedCodec implements SchemaUnawareCodec } final MethodHandle ctor = MethodHandles.publicLookup().unreflectConstructor(constructor) - .asSpreader(Boolean[].class, valueGetters.size()).asType(CONSTRUCTOR_INVOKE_TYPE); - return new BitsCodec(returnType, valueGetters, ctor); + .asSpreader(Boolean[].class, ctorArgs.size()).asType(CONSTRUCTOR_INVOKE_TYPE); + return new BitsCodec(returnType, ctor, ctorArgs, getters); }; } @@ -63,42 +73,43 @@ final class BitsCodec extends ReflectionBasedCodec implements SchemaUnawareCodec public Object deserialize(final Object input) { Preconditions.checkArgument(input instanceof Set); @SuppressWarnings("unchecked") - Set casted = (Set) input; + final Set casted = (Set) input; - final Boolean args[] = new Boolean[valueGetters.size()]; - int currentArg = 0; /* - * We can do this walk based on field set - * sorted by name, since constructor arguments in - * Java Binding are sorted by name. + * We can do this walk based on field set sorted by name, + * since constructor arguments in Java Binding are sorted by name. * - * This means we will construct correct array - * for construction of bits object. + * This means we will construct correct array for construction + * of bits object. */ - for (String value : valueGetters.keySet()) { + final Boolean args[] = new Boolean[ctorArgs.size()]; + int currentArg = 0; + for (String value : ctorArgs) { args[currentArg++] = casted.contains(value); } try { - return constructor.invokeExact(args); + return ctor.invokeExact(args); } catch (Throwable e) { throw new IllegalStateException("Failed to instantiate object for " + input, e); } } @Override - public Object serialize(final Object input) { - Set result = new HashSet<>(); - for (Entry valueGet : valueGetters.entrySet()) { + public Set serialize(final Object input) { + final Collection result = new ArrayList<>(getters.size()); + for (Entry valueGet : getters.entrySet()) { + final Boolean value; try { - Boolean value = (Boolean) valueGet.getValue().invoke(input); - if (value) { - result.add(valueGet.getKey()); - } + value = (Boolean) valueGet.getValue().invoke(input); } catch (IllegalAccessException | InvocationTargetException e) { - throw new IllegalArgumentException(e); + throw new IllegalArgumentException("Failed to get bit " + valueGet.getKey(), e); + } + + if (value) { + result.add(valueGet.getKey()); } } - return result; + return result.size() == getters.size() ? getters.keySet() : ImmutableSet.copyOf(result); } -} \ No newline at end of file +}