From cbdbbd189b62414d5299af396a3c0fbfbab6dd9e Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Tue, 17 Dec 2019 12:56:56 +0100 Subject: [PATCH] Add PathArgument uint adaptation Legacy uint values may be present in NodeWithValue as well as NodeIdentifierWithPredicates. Make sure we run the appropriate adaptation. JIRA: CONTROLLER-1923 Change-Id: Ib59adb9e596e4d63110cbe9987feeedc61cb05eb Signed-off-by: Robert Varga --- .../AbstractNormalizedNodePruner.java | 16 +- .../ReusableNormalizedNodePruner.java | 51 ---- .../utils/transformer/UintAdaptingPruner.java | 218 ++++++++++++++++++ .../transformer/UintAdaptingPrunerTest.java | 215 +++++++++++++++++ .../src/test/resources/odl-ctlr1923.yang | 43 ++++ 5 files changed, 486 insertions(+), 57 deletions(-) create mode 100644 opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/transformer/UintAdaptingPruner.java create mode 100644 opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/node/utils/transformer/UintAdaptingPrunerTest.java create mode 100644 opendaylight/md-sal/sal-clustering-commons/src/test/resources/odl-ctlr1923.yang diff --git a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/transformer/AbstractNormalizedNodePruner.java b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/transformer/AbstractNormalizedNodePruner.java index d6d409cead..ae6950df6f 100644 --- a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/transformer/AbstractNormalizedNodePruner.java +++ b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/transformer/AbstractNormalizedNodePruner.java @@ -45,13 +45,13 @@ abstract class AbstractNormalizedNodePruner implements NormalizedNodeStreamWrite } @FunctionalInterface - private interface WriterMethod { + interface WriterMethod { void apply(ReusableImmutableNormalizedNodeStreamWriter writer, T name) throws IOException; } @FunctionalInterface - private interface SizedWriterMethod { + interface SizedWriterMethod { void apply(ReusableImmutableNormalizedNodeStreamWriter writer, T name, int childSizeHint) throws IOException; } @@ -185,7 +185,7 @@ abstract class AbstractNormalizedNodePruner implements NormalizedNodeStreamWrite public void scalarValue(final Object value) throws IOException { checkNotSealed(); if (unknown == 0) { - delegate.scalarValue(translateScalar(stack.peek(), value)); + delegate.scalarValue(translateScalar(currentSchema(), value)); } } @@ -256,7 +256,7 @@ abstract class AbstractNormalizedNodePruner implements NormalizedNodeStreamWrite } final DataSchemaContextNode schema; - final DataSchemaContextNode parent = stack.peek(); + final DataSchemaContextNode parent = currentSchema(); if (parent != null) { schema = parent.getChild(name); } else { @@ -277,16 +277,20 @@ abstract class AbstractNormalizedNodePruner implements NormalizedNodeStreamWrite return true; } - private void enter(final WriterMethod method, final A name) throws IOException { + final void enter(final WriterMethod method, final A name) throws IOException { if (enter(name)) { method.apply(delegate, name); } } - private void enter(final SizedWriterMethod method, final A name, final int size) + final void enter(final SizedWriterMethod method, final A name, final int size) throws IOException { if (enter(name)) { method.apply(delegate, name, size); } } + + final DataSchemaContextNode currentSchema() { + return stack.peek(); + } } diff --git a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/transformer/ReusableNormalizedNodePruner.java b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/transformer/ReusableNormalizedNodePruner.java index 751c96f2b6..f4e5133586 100644 --- a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/transformer/ReusableNormalizedNodePruner.java +++ b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/transformer/ReusableNormalizedNodePruner.java @@ -8,26 +8,10 @@ package org.opendaylight.controller.cluster.datastore.node.utils.transformer; import com.google.common.annotations.Beta; -import java.io.IOException; -import java.math.BigInteger; import org.eclipse.jdt.annotation.NonNull; -import org.opendaylight.yangtools.yang.common.Uint16; -import org.opendaylight.yangtools.yang.common.Uint32; -import org.opendaylight.yangtools.yang.common.Uint64; -import org.opendaylight.yangtools.yang.common.Uint8; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; -import org.opendaylight.yangtools.yang.data.util.DataSchemaContextNode; import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree; -import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; import org.opendaylight.yangtools.yang.model.api.SchemaContext; -import org.opendaylight.yangtools.yang.model.api.TypeDefinition; -import org.opendaylight.yangtools.yang.model.api.TypedDataSchemaNode; -import org.opendaylight.yangtools.yang.model.api.type.Uint16TypeDefinition; -import org.opendaylight.yangtools.yang.model.api.type.Uint32TypeDefinition; -import org.opendaylight.yangtools.yang.model.api.type.Uint64TypeDefinition; -import org.opendaylight.yangtools.yang.model.api.type.Uint8TypeDefinition; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * The NormalizedNodePruner removes all nodes from the input NormalizedNode that do not have a corresponding @@ -54,41 +38,6 @@ public abstract class ReusableNormalizedNodePruner extends AbstractNormalizedNod } } - private static final class UintAdaptingPruner extends ReusableNormalizedNodePruner { - private static final Logger LOG = LoggerFactory.getLogger(UintAdaptingPruner.class); - - UintAdaptingPruner(final DataSchemaContextTree tree) { - super(tree); - } - - @Override - public ReusableNormalizedNodePruner duplicate() { - return new UintAdaptingPruner(getTree()); - } - - @Override - Object translateScalar(final DataSchemaContextNode context, final Object value) throws IOException { - final DataSchemaNode schema = context.getDataSchemaNode(); - if (schema instanceof TypedDataSchemaNode) { - final TypeDefinition type = ((TypedDataSchemaNode) schema).getType(); - if (value instanceof Short && type instanceof Uint8TypeDefinition) { - LOG.trace("Translating legacy uint8 {}", value); - return Uint8.valueOf((Short) value); - } else if (value instanceof Integer && type instanceof Uint16TypeDefinition) { - LOG.trace("Translating legacy uint16 {}", value); - return Uint16.valueOf((Integer) value); - } else if (value instanceof Long && type instanceof Uint32TypeDefinition) { - LOG.trace("Translating legacy uint32 {}", value); - return Uint32.valueOf((Long) value); - } else if (value instanceof BigInteger && type instanceof Uint64TypeDefinition) { - LOG.trace("Translating legacy uint64 {}", value); - return Uint64.valueOf((BigInteger) value); - } - } - return value; - } - } - ReusableNormalizedNodePruner(final SchemaContext schemaContext) { super(schemaContext); } diff --git a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/transformer/UintAdaptingPruner.java b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/transformer/UintAdaptingPruner.java new file mode 100644 index 0000000000..b3e02a4761 --- /dev/null +++ b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/transformer/UintAdaptingPruner.java @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2019 PANTHEON.tech, s.r.o. 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.controller.cluster.datastore.node.utils.transformer; + +import static com.google.common.base.Verify.verify; + +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.google.common.collect.ImmutableMap; +import java.io.IOException; +import java.math.BigInteger; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.function.Function; +import org.eclipse.jdt.annotation.Nullable; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.Uint16; +import org.opendaylight.yangtools.yang.common.Uint32; +import org.opendaylight.yangtools.yang.common.Uint64; +import org.opendaylight.yangtools.yang.common.Uint8; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue; +import org.opendaylight.yangtools.yang.data.impl.schema.ReusableImmutableNormalizedNodeStreamWriter; +import org.opendaylight.yangtools.yang.data.util.DataSchemaContextNode; +import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode; +import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; +import org.opendaylight.yangtools.yang.model.api.TypeDefinition; +import org.opendaylight.yangtools.yang.model.api.TypedDataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.type.Uint16TypeDefinition; +import org.opendaylight.yangtools.yang.model.api.type.Uint32TypeDefinition; +import org.opendaylight.yangtools.yang.model.api.type.Uint64TypeDefinition; +import org.opendaylight.yangtools.yang.model.api.type.Uint8TypeDefinition; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +final class UintAdaptingPruner extends ReusableNormalizedNodePruner { + @FunctionalInterface + private interface NipAdapter extends Function { + + } + + private enum ValueAdapter implements Function { + UINT8 { + @Override + public Object apply(final Object obj) { + if (obj instanceof Short) { + LOG.trace("Translating legacy uint8 {}", obj); + return Uint8.valueOf((Short) obj); + } + return obj; + } + }, + UINT16 { + @Override + public Object apply(final Object obj) { + if (obj instanceof Integer) { + LOG.trace("Translating legacy uint16 {}", obj); + return Uint16.valueOf((Integer) obj); + } + return obj; + } + }, + UINT32 { + @Override + public Object apply(final Object obj) { + if (obj instanceof Long) { + LOG.trace("Translating legacy uint32 {}", obj); + return Uint32.valueOf((Long) obj); + } + return obj; + } + }, + UINT64 { + @Override + public Object apply(final Object obj) { + if (obj instanceof BigInteger) { + LOG.trace("Translating legacy uint64 {}", obj); + return Uint64.valueOf((BigInteger) obj); + } + return obj; + } + }; + + private static final Logger LOG = LoggerFactory.getLogger(ValueAdapter.class); + + static @Nullable ValueAdapter forType(final TypeDefinition type) { + if (type instanceof Uint8TypeDefinition) { + return UINT8; + } else if (type instanceof Uint16TypeDefinition) { + return UINT16; + } else if (type instanceof Uint32TypeDefinition) { + return UINT32; + } else if (type instanceof Uint64TypeDefinition) { + return UINT64; + } else { + return null; + } + } + } + + private static final LoadingCache NIP_ADAPTERS = CacheBuilder.newBuilder() + .weakKeys().build(new AdapterCacheLoader()); + + UintAdaptingPruner(final DataSchemaContextTree tree) { + super(tree); + } + + @Override + public ReusableNormalizedNodePruner duplicate() { + return new UintAdaptingPruner(getTree()); + } + + @Override + public void startMapEntryNode(final NodeIdentifierWithPredicates identifier, final int childSizeHint) + throws IOException { + enter(this::adaptEntry, identifier, childSizeHint); + } + + @Override + public void startLeafSetEntryNode(final NodeWithValue name) throws IOException { + enter(this::adaptEntry, name); + } + + @Override + Object translateScalar(final DataSchemaContextNode context, final Object value) throws IOException { + final DataSchemaNode schema = context.getDataSchemaNode(); + return schema instanceof TypedDataSchemaNode ? adaptValue(((TypedDataSchemaNode) schema).getType(), value) + : value; + } + + private void adaptEntry(final ReusableImmutableNormalizedNodeStreamWriter writer, final NodeWithValue name) { + final NodeWithValue adapted; + final DataSchemaNode schema = currentSchema().getDataSchemaNode(); + if (schema instanceof TypedDataSchemaNode) { + final Object oldValue = name.getValue(); + final Object newValue = adaptValue(((TypedDataSchemaNode) schema).getType(), oldValue); + adapted = newValue == oldValue ? name : new NodeWithValue<>(name.getNodeType(), newValue); + } else { + adapted = name; + } + + writer.startLeafSetEntryNode(adapted); + } + + private void adaptEntry(final ReusableImmutableNormalizedNodeStreamWriter writer, + final NodeIdentifierWithPredicates name, final int size) { + final NodeIdentifierWithPredicates adapted; + final DataSchemaNode schema = currentSchema().getDataSchemaNode(); + if (schema instanceof ListSchemaNode) { + adapted = NIP_ADAPTERS.getUnchecked((ListSchemaNode) schema).apply(name); + } else { + adapted = name; + } + + writer.startMapEntryNode(adapted, size); + } + + private static Object adaptValue(final TypeDefinition type, final Object value) { + final ValueAdapter adapter = ValueAdapter.forType(type); + return adapter != null ? adapter.apply(value) : value; + } + + private static final class AdapterCacheLoader extends CacheLoader { + @Override + public NipAdapter load(final ListSchemaNode key) { + final Map adapters = new HashMap<>(); + + for (QName qname : key.getKeyDefinition()) { + final DataSchemaNode child; + try { + child = key.findDataTreeChild(qname).orElseThrow(); + } catch (NoSuchElementException e) { + throw new IllegalStateException("Failed to find child " + qname, e); + } + + verify(child instanceof LeafSchemaNode, "Key references non-leaf child %s", child); + final ValueAdapter adapter = ValueAdapter.forType(((LeafSchemaNode) child).getType()); + if (adapter != null) { + adapters.put(qname, adapter); + } + } + + return adapters.isEmpty() ? name -> name : new TransformingNipAdapter(adapters); + } + } + + private static final class TransformingNipAdapter implements NipAdapter { + private final ImmutableMap adapters; + + TransformingNipAdapter(final Map toTransform) { + adapters = ImmutableMap.copyOf(toTransform); + } + + @Override + public NodeIdentifierWithPredicates apply(final NodeIdentifierWithPredicates name) { + final Set> entries = name.entrySet(); + final ImmutableMap.Builder newEntries = ImmutableMap.builderWithExpectedSize(entries.size()); + for (Entry e : entries) { + final QName qname = e.getKey(); + final ValueAdapter adapter = adapters.get(qname); + newEntries.put(qname, adapter != null ? adapter.apply(e.getValue()) : e.getValue()); + } + + return NodeIdentifierWithPredicates.of(name.getNodeType(), newEntries.build()); + } + } +} diff --git a/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/node/utils/transformer/UintAdaptingPrunerTest.java b/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/node/utils/transformer/UintAdaptingPrunerTest.java new file mode 100644 index 0000000000..33f6058ea7 --- /dev/null +++ b/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/node/utils/transformer/UintAdaptingPrunerTest.java @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2020 PANTHEON.tech, s.r.o. 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.controller.cluster.datastore.node.utils.transformer; + +import static org.junit.Assert.assertEquals; + +import com.google.common.collect.ImmutableMap; +import java.io.IOException; +import java.math.BigInteger; +import org.junit.BeforeClass; +import org.junit.Test; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.Uint16; +import org.opendaylight.yangtools.yang.common.Uint32; +import org.opendaylight.yangtools.yang.common.Uint64; +import org.opendaylight.yangtools.yang.common.Uint8; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter; +import org.opendaylight.yangtools.yang.data.impl.schema.Builders; +import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes; +import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext; +import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils; + +public class UintAdaptingPrunerTest { + private static final QName CONT = QName.create("urn:odl-ctlr1923", "cont"); + private static final QName LST = QName.create(CONT, "lst"); + private static final QName LFLST8 = QName.create(CONT, "lf-lst8"); + private static final QName LFLST16 = QName.create(CONT, "lf-lst16"); + private static final QName LFLST32 = QName.create(CONT, "lf-lst32"); + private static final QName LFLST64 = QName.create(CONT, "lf-lst64"); + private static final QName A = QName.create(LST, "a"); + private static final QName B = QName.create(LST, "b"); + private static final QName C = QName.create(LST, "c"); + private static final QName D = QName.create(LST, "d"); + private static final QName E = QName.create(LST, "e"); + private static final QName F = QName.create(LST, "f"); + private static final QName G = QName.create(LST, "g"); + private static final QName H = QName.create(LST, "h"); + + private static EffectiveModelContext CONTEXT; + + @BeforeClass + public static void beforeClass() { + CONTEXT = YangParserTestUtils.parseYangResource("/odl-ctlr1923.yang"); + } + + @Test + public void testListTranslation() throws IOException { + assertEquals(Builders.mapBuilder() + .withNodeIdentifier(new NodeIdentifier(LST)) + .withChild(Builders.mapEntryBuilder() + .withNodeIdentifier(NodeIdentifierWithPredicates.of(LST, ImmutableMap.builder() + .put(A, (byte) 1) + .put(B, (short) 1) + .put(C, 1) + .put(D, 1L) + .put(E, Uint8.ONE) + .put(F, Uint16.ONE) + .put(G, Uint32.ONE) + .put(H, Uint64.ONE) + .build())) + .withChild(ImmutableNodes.leafNode(A, (byte) 1)) + .withChild(ImmutableNodes.leafNode(B, (short) 1)) + .withChild(ImmutableNodes.leafNode(C, 1)) + .withChild(ImmutableNodes.leafNode(D, 1L)) + .withChild(ImmutableNodes.leafNode(E, Uint8.ONE)) + .withChild(ImmutableNodes.leafNode(F, Uint16.ONE)) + .withChild(ImmutableNodes.leafNode(G, Uint32.ONE)) + .withChild(ImmutableNodes.leafNode(H, Uint64.ONE)) + .build()) + .build(), + prune(Builders.mapBuilder() + .withNodeIdentifier(new NodeIdentifier(LST)) + .withChild(Builders.mapEntryBuilder() + .withNodeIdentifier(NodeIdentifierWithPredicates.of(LST, ImmutableMap.builder() + .put(A, (byte) 1) + .put(B, (short) 1) + .put(C, 1) + .put(D, 1L) + .put(E, (short) 1) + .put(F, 1) + .put(G, 1L) + .put(H, BigInteger.ONE) + .build())) + .withChild(ImmutableNodes.leafNode(A, (byte) 1)) + .withChild(ImmutableNodes.leafNode(B, (short) 1)) + .withChild(ImmutableNodes.leafNode(C, 1)) + .withChild(ImmutableNodes.leafNode(D, 1L)) + .withChild(ImmutableNodes.leafNode(E, (short) 1)) + .withChild(ImmutableNodes.leafNode(F, 1)) + .withChild(ImmutableNodes.leafNode(G, 1L)) + .withChild(ImmutableNodes.leafNode(H, BigInteger.ONE)) + .build()) + .build())); + } + + @Test + public void testContainerTranslation() throws IOException { + assertEquals(Builders.containerBuilder() + .withNodeIdentifier(new NodeIdentifier(CONT)) + .withChild(ImmutableNodes.leafNode(A, (byte) 1)) + .withChild(ImmutableNodes.leafNode(B, (short) 1)) + .withChild(ImmutableNodes.leafNode(C, 1)) + .withChild(ImmutableNodes.leafNode(D, 1L)) + .withChild(ImmutableNodes.leafNode(E, Uint8.ONE)) + .withChild(ImmutableNodes.leafNode(F, Uint16.ONE)) + .withChild(ImmutableNodes.leafNode(G, Uint32.ONE)) + .withChild(ImmutableNodes.leafNode(H, Uint64.ONE)) + .build(), + prune(Builders.containerBuilder() + .withNodeIdentifier(new NodeIdentifier(CONT)) + .withChild(ImmutableNodes.leafNode(A, (byte) 1)) + .withChild(ImmutableNodes.leafNode(B, (short) 1)) + .withChild(ImmutableNodes.leafNode(C, 1)) + .withChild(ImmutableNodes.leafNode(D, 1L)) + .withChild(ImmutableNodes.leafNode(E, (short) 1)) + .withChild(ImmutableNodes.leafNode(F, 1)) + .withChild(ImmutableNodes.leafNode(G, 1L)) + .withChild(ImmutableNodes.leafNode(H, BigInteger.ONE)) + .build())); + } + + @Test + public void testLeafList8() throws IOException { + assertEquals(Builders.leafSetBuilder() + .withNodeIdentifier(new NodeIdentifier(LFLST8)) + .withChild(Builders.leafSetEntryBuilder() + .withNodeIdentifier(new NodeWithValue<>(LFLST8, Uint8.ONE)) + .withValue(Uint8.ONE) + .build()) + .build(), + prune(Builders.leafSetBuilder() + .withNodeIdentifier(new NodeIdentifier(LFLST8)) + .withChild(Builders.leafSetEntryBuilder() + .withNodeIdentifier(new NodeWithValue<>(LFLST8, (short) 1)) + .withValue((short) 1) + .build()) + .build())); + } + + @Test + public void testLeafList16() throws IOException { + assertEquals(Builders.leafSetBuilder() + .withNodeIdentifier(new NodeIdentifier(LFLST16)) + .withChild(Builders.leafSetEntryBuilder() + .withNodeIdentifier(new NodeWithValue<>(LFLST16, Uint16.ONE)) + .withValue(Uint16.ONE) + .build()) + .build(), + prune(Builders.leafSetBuilder() + .withNodeIdentifier(new NodeIdentifier(LFLST16)) + .withChild(Builders.leafSetEntryBuilder() + .withNodeIdentifier(new NodeWithValue<>(LFLST16, 1)) + .withValue(1) + .build()) + .build())); + } + + @Test + public void testLeafList32() throws IOException { + assertEquals(Builders.leafSetBuilder() + .withNodeIdentifier(new NodeIdentifier(LFLST32)) + .withChild(Builders.leafSetEntryBuilder() + .withNodeIdentifier(new NodeWithValue<>(LFLST32, Uint32.ONE)) + .withValue(Uint32.ONE) + .build()) + .build(), + prune(Builders.leafSetBuilder() + .withNodeIdentifier(new NodeIdentifier(LFLST32)) + .withChild(Builders.leafSetEntryBuilder() + .withNodeIdentifier(new NodeWithValue<>(LFLST32, 1L)) + .withValue(1L) + .build()) + .build())); + } + + @Test + public void testLeafList64() throws IOException { + assertEquals(Builders.leafSetBuilder() + .withNodeIdentifier(new NodeIdentifier(LFLST64)) + .withChild(Builders.leafSetEntryBuilder() + .withNodeIdentifier(new NodeWithValue<>(LFLST64, Uint64.ONE)) + .withValue(Uint64.ONE) + .build()) + .build(), + prune(Builders.leafSetBuilder() + .withNodeIdentifier(new NodeIdentifier(LFLST64)) + .withChild(Builders.leafSetEntryBuilder() + .withNodeIdentifier(new NodeWithValue<>(LFLST64, BigInteger.ONE)) + .withValue(BigInteger.ONE) + .build()) + .build())); + } + + private static NormalizedNode prune(final NormalizedNode node) throws IOException { + final ReusableNormalizedNodePruner pruner = ReusableNormalizedNodePruner.forSchemaContext(CONTEXT) + .withUintAdaption(); + pruner.initializeForPath(YangInstanceIdentifier.create(node.getIdentifier())); + + try (NormalizedNodeWriter writer = NormalizedNodeWriter.forStreamWriter(pruner)) { + writer.write(node); + } + pruner.close(); + return pruner.getResult().get(); + } +} diff --git a/opendaylight/md-sal/sal-clustering-commons/src/test/resources/odl-ctlr1923.yang b/opendaylight/md-sal/sal-clustering-commons/src/test/resources/odl-ctlr1923.yang new file mode 100644 index 0000000000..9ad4f7258a --- /dev/null +++ b/opendaylight/md-sal/sal-clustering-commons/src/test/resources/odl-ctlr1923.yang @@ -0,0 +1,43 @@ +module odl-ctrl1923 { + yang-version 1; + namespace "urn:odl-ctlr1923"; + prefix "ctrl1923"; + + description "Sodium -> Magnesium uint translation"; + + grouping grp { + leaf a { type int8; } + leaf b { type int16; } + leaf c { type int32; } + leaf d { type int64; } + leaf e { type uint8; } + leaf f { type uint16; } + leaf g { type uint32; } + leaf h { type uint64; } + } + + container cont { + uses grp; + } + + list lst { + key "a b c d e f g h"; + uses grp; + } + + leaf-list lf-lst8 { + type uint8; + } + + leaf-list lf-lst16 { + type uint16; + } + + leaf-list lf-lst32 { + type uint32; + } + + leaf-list lf-lst64 { + type uint64; + } +} -- 2.36.6