From 12b665bc9f60d2acdfb38549a091848338b1d38b Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Mon, 18 Nov 2019 12:30:08 +0100 Subject: [PATCH] Map system-ordered keyed lists to Map The type mapping for YANG lists which have a key and do not have a user-specified order should point to java.util.Map, as that provides the correct semantics. This patch changes that mapping, resulting in better ergonomics, as it is now possible to acquire specific items based on their keys. JIRA: MDSAL-434 Change-Id: If2f8980fde1c419bbc0b7c414d7deab329362b47 Signed-off-by: Robert Varga --- .../ForwardedNotificationAdapterTest.java | 9 +-- .../dom/adapter/test/Mdsal108Test.java | 8 +-- .../dom/codec/impl/DataObjectStreamer.java | 4 +- .../impl/DataObjectStreamerGenerator.java | 25 +++++-- .../codec/impl/KeyedListNodeCodecContext.java | 66 +++++++++++++++++-- .../dom/codec/impl/ListNodeCodecContext.java | 6 +- .../test/AugmentationSubstitutionTest.java | 6 +- .../dom/codec/test/Bug5845booleanKeyTest.java | 20 +++--- .../dom/codec/test/CachingCodecTest.java | 19 +++--- .../dom/codec/test/CaseSubstitutionTest.java | 9 +-- .../binding/dom/codec/test/EmptyLeafTest.java | 10 ++- .../dom/codec/test/KeyInheritenceTest.java | 6 +- ...ormalizedNodeSerializeDeserializeTest.java | 2 +- .../test/NotificationProcessingTest.java | 6 +- .../codec/test/RpcDataSerializationTest.java | 18 ++--- .../generator/impl/AbstractTypeGenerator.java | 10 ++- .../impl/ChoiceCaseGenTypesTest.java | 4 +- .../mdsal/binding/model/util/Types.java | 8 +++ .../java/api/generator/BuilderTemplate.xtend | 8 ++- .../test/model/util/ListsBindingUtils.java | 9 +-- .../testutils/AssertDataObjectsTest.java | 16 ++--- .../testutils/AugmentableExtensionTest.java | 2 +- .../binding/testutils/ExpectedObjects.java | 5 +- .../rfc7895/MountPointContextFactoryImpl.java | 4 +- .../rfc8525/MountPointContextFactoryImpl.java | 32 ++++----- 25 files changed, 198 insertions(+), 114 deletions(-) diff --git a/binding/mdsal-binding-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/dom/adapter/test/ForwardedNotificationAdapterTest.java b/binding/mdsal-binding-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/dom/adapter/test/ForwardedNotificationAdapterTest.java index 0668b167ba..f5a761c2cb 100644 --- a/binding/mdsal-binding-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/dom/adapter/test/ForwardedNotificationAdapterTest.java +++ b/binding/mdsal-binding-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/dom/adapter/test/ForwardedNotificationAdapterTest.java @@ -11,7 +11,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertTrue; -import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import java.util.ArrayList; import java.util.List; @@ -45,9 +45,10 @@ public class ForwardedNotificationAdapterTest extends AbstractNotificationBroker } private static TwoLevelListChanged createTestData() { - final TwoLevelListChangedBuilder tb = new TwoLevelListChangedBuilder(); - tb.setTopLevelList(ImmutableList.of(new TopLevelListBuilder().withKey(new TopLevelListKey("test")).build())); - return tb.build(); + final TopLevelListKey key = new TopLevelListKey("test"); + return new TwoLevelListChangedBuilder() + .setTopLevelList(ImmutableMap.of(key, new TopLevelListBuilder().withKey(key).build())) + .build(); } @Test diff --git a/binding/mdsal-binding-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/dom/adapter/test/Mdsal108Test.java b/binding/mdsal-binding-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/dom/adapter/test/Mdsal108Test.java index cf4668a15f..006283538e 100644 --- a/binding/mdsal-binding-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/dom/adapter/test/Mdsal108Test.java +++ b/binding/mdsal-binding-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/dom/adapter/test/Mdsal108Test.java @@ -7,7 +7,7 @@ */ package org.opendaylight.mdsal.binding.dom.adapter.test; -import java.util.ArrayList; +import java.util.Collections; import org.junit.Test; import org.opendaylight.mdsal.binding.api.DataBroker; import org.opendaylight.mdsal.binding.api.ReadWriteTransaction; @@ -25,9 +25,9 @@ public class Mdsal108Test extends AbstractDataBrokerTest { public void testDelete() { DataBroker dataBroker = getDataBroker(); WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction(); - ArrayList list = new ArrayList<>(); - list.add(new TopLevelListBuilder().setName("name").build()); - TopBuilder builder = new TopBuilder().setTopLevelList(list); + + final TopLevelList item = new TopLevelListBuilder().setName("name").build(); + TopBuilder builder = new TopBuilder().setTopLevelList(Collections.singletonMap(item.key(), item)); writeTransaction.put(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(Top.class), builder.build()); assertCommit(writeTransaction.commit()); diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectStreamer.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectStreamer.java index 59ca8b0b8c..ab8ef78532 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectStreamer.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectStreamer.java @@ -144,10 +144,10 @@ public abstract class DataObjectStreamer implements DataOb protected static final > void streamMap(final Class childClass, final DataObjectStreamer childStreamer, final DataObjectSerializerRegistry registry, - final BindingStreamEventWriter writer, final List value) throws IOException { + final BindingStreamEventWriter writer, final Map value) throws IOException { if (value != null) { writer.startMapNode(childClass, value.size()); - commonStreamList(registry, writer, childStreamer, value); + commonStreamList(registry, writer, childStreamer, value.values()); } } diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectStreamerGenerator.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectStreamerGenerator.java index f601b0628c..5a3bc3d229 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectStreamerGenerator.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectStreamerGenerator.java @@ -144,7 +144,7 @@ final class DataObjectStreamerGenerator> impleme BindingStreamEventWriter.class, List.class); private static final StackManipulation STREAM_MAP = invokeMethod(DataObjectStreamer.class, "streamMap", Class.class, DataObjectStreamer.class, DataObjectSerializerRegistry.class, - BindingStreamEventWriter.class, List.class); + BindingStreamEventWriter.class, Map.class); private static final StackManipulation STREAM_ORDERED_MAP = invokeMethod(DataObjectStreamer.class, "streamOrderedMap", Class.class, DataObjectStreamer.class, DataObjectSerializerRegistry.class, BindingStreamEventWriter.class, List.class); @@ -257,14 +257,17 @@ final class DataObjectStreamerGenerator> impleme final String getterName = getter.getName(); final Type childType = props.get(getterName); verify(childType instanceof ParameterizedType, "Unexpected type %s for %s", childType, getterName); - final Type valueType = ((ParameterizedType) childType).getActualTypeArguments()[0]; + final Type[] params = ((ParameterizedType) childType).getActualTypeArguments(); + final ListSchemaNode listSchema = (ListSchemaNode) childSchema; final Class valueClass; - try { - valueClass = loader.loadClass(valueType.getFullyQualifiedName()); - } catch (ClassNotFoundException e) { - throw new LinkageError("Failed to load " + valueType, e); + if (!listSchema.isUserOrdered() && !listSchema.getKeyDefinition().isEmpty()) { + loadTypeClass(loader, params[0]); + valueClass = loadTypeClass(loader, params[1]); + } else { + valueClass = loadTypeClass(loader, params[0]); } - return listChildStream(getter, valueClass.asSubclass(DataObject.class), (ListSchemaNode) childSchema); + + return listChildStream(getter, valueClass.asSubclass(DataObject.class), listSchema); } if (childSchema instanceof ChoiceSchemaNode) { return choiceChildStream(getter); @@ -374,6 +377,14 @@ final class DataObjectStreamerGenerator> impleme } } + private static Class loadTypeClass(final CodecClassLoader loader, final Type type) { + try { + return loader.loadClass(type.getFullyQualifiedName()); + } catch (ClassNotFoundException e) { + throw new LinkageError("Failed to load " + type, e); + } + } + private static final class SerializeImplementation implements Implementation { private final List children; private final StackManipulation startEvent; diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/KeyedListNodeCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/KeyedListNodeCodecContext.java index 62dd9b74c1..33515324b2 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/KeyedListNodeCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/KeyedListNodeCodecContext.java @@ -10,8 +10,16 @@ package org.opendaylight.mdsal.binding.dom.codec.impl; import static java.util.Objects.requireNonNull; import static org.opendaylight.mdsal.binding.spec.naming.BindingMapping.IDENTIFIABLE_KEY_NAME; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMap.Builder; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.invoke.WrongMethodTypeException; import java.lang.reflect.Method; +import java.util.Collection; import java.util.List; +import java.util.Map; import org.eclipse.jdt.annotation.NonNull; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.Identifiable; @@ -20,12 +28,59 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates; +import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode; +import org.opendaylight.yangtools.yang.data.api.schema.MapNode; import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; -final class KeyedListNodeCodecContext> extends ListNodeCodecContext { +abstract class KeyedListNodeCodecContext> extends ListNodeCodecContext { + private static final class Ordered> extends KeyedListNodeCodecContext { + Ordered(final DataContainerCodecPrototype prototype, final Method keyMethod, + final IdentifiableItemCodec codec) { + super(prototype, keyMethod, codec); + } + } + + private static final class Unordered> extends KeyedListNodeCodecContext { + private static final MethodType KEY_TYPE = MethodType.methodType(Object.class, DataObject.class); + + private final MethodHandle keyHandle; + + Unordered(final DataContainerCodecPrototype prototype, final Method keyMethod, + final IdentifiableItemCodec codec) { + super(prototype, keyMethod, codec); + + try { + this.keyHandle = MethodHandles.publicLookup().unreflect(keyMethod).asType(KEY_TYPE); + } catch (IllegalAccessException | WrongMethodTypeException e) { + throw new LinkageError("Failed to acquire method " + keyMethod, e); + } + } + + @Override + Map fromMap(final MapNode nodes) { + final Collection value = nodes.getValue(); + final Builder builder = ImmutableMap.builderWithExpectedSize(value.size()); + // FIXME: Could be this lazy transformed map? + for (MapEntryNode node : value) { + final D entry = fromMapEntry(node); + builder.put(getKey(entry), entry); + } + return builder.build(); + } + + @SuppressWarnings("checkstyle:illegalCatch") + private Object getKey(final D entry) { + try { + return keyHandle.invokeExact(entry); + } catch (Throwable e) { + throw new LinkageError("Failed to extract key from " + entry, e); + } + } + } + private final IdentifiableItemCodec codec; - private KeyedListNodeCodecContext(final DataContainerCodecPrototype prototype, + KeyedListNodeCodecContext(final DataContainerCodecPrototype prototype, final Method keyMethod, final IdentifiableItemCodec codec) { super(prototype, keyMethod); this.codec = requireNonNull(codec); @@ -41,9 +96,10 @@ final class KeyedListNodeCodecContext> ex throw new IllegalStateException("Required method not available", e); } - final IdentifiableItemCodec codec = prototype.getFactory().getPathArgumentCodec(bindingClass, - prototype.getSchema()); - return new KeyedListNodeCodecContext<>(prototype, keyMethod, codec); + final ListSchemaNode schema = prototype.getSchema(); + final IdentifiableItemCodec codec = prototype.getFactory().getPathArgumentCodec(bindingClass, schema); + return schema.isUserOrdered() ? new Ordered<>(prototype, keyMethod, codec) + : new Unordered<>(prototype, keyMethod, codec); } @Override diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ListNodeCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ListNodeCodecContext.java index 9d38ded24d..fe7a093637 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ListNodeCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ListNodeCodecContext.java @@ -56,17 +56,17 @@ class ListNodeCodecContext extends DataObjectCodecContext< } } - private List fromMap(final MapNode nodes) { + Object fromMap(final MapNode nodes) { final Collection value = nodes.getValue(); final Builder builder = ImmutableList.builderWithExpectedSize(value.size()); // FIXME: Could be this lazy transformed list? for (MapEntryNode node : value) { - builder.add(fromMapEntry(node)); + builder.add(createBindingProxy(node)); } return builder.build(); } - private D fromMapEntry(final MapEntryNode node) { + final D fromMapEntry(final MapEntryNode node) { return createBindingProxy(node); } diff --git a/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/test/AugmentationSubstitutionTest.java b/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/test/AugmentationSubstitutionTest.java index 144a5b4d9a..333a2eed47 100644 --- a/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/test/AugmentationSubstitutionTest.java +++ b/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/test/AugmentationSubstitutionTest.java @@ -71,10 +71,8 @@ public class AugmentationSubstitutionTest extends AbstractBindingCodecTest { private static RpcComplexUsesAugment createComplexData() { return new RpcComplexUsesAugmentBuilder() - .setContainerWithUses(new ContainerWithUsesBuilder() - .setLeafFromGrouping("foo") - .build()) - .setListViaUses(Collections.emptyList()) + .setContainerWithUses(new ContainerWithUsesBuilder().setLeafFromGrouping("foo").build()) + .setListViaUses(Collections.emptyMap()) .build(); } } diff --git a/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/test/Bug5845booleanKeyTest.java b/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/test/Bug5845booleanKeyTest.java index 7eb3b8919a..0cf3b74471 100644 --- a/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/test/Bug5845booleanKeyTest.java +++ b/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/test/Bug5845booleanKeyTest.java @@ -25,17 +25,19 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; public class Bug5845booleanKeyTest extends AbstractBindingCodecTest { @Test public void testBug5845() throws Exception { - final BooleanContainer booleanContainer = new BooleanContainerBuilder().setBooleanList(Collections - .singletonList(new BooleanListBuilder() - .withKey(new BooleanListKey(true, true)) - .setBooleanLeaf1(true) - .setBooleanLeaf2(true) - .build())) + final BooleanListKey blk = new BooleanListKey(true, true); + final BooleanContainer booleanContainer = new BooleanContainerBuilder() + .setBooleanList(Collections.singletonMap(blk, new BooleanListBuilder() + .withKey(blk) + .setBooleanLeaf1(true) + .setBooleanLeaf2(true) + .build())) .build(); - final BooleanContainer booleanContainerInt = new BooleanContainerBuilder().setBooleanListInt(Collections - .singletonList(new BooleanListIntBuilder() - .withKey(new BooleanListIntKey((byte) 1)) + final BooleanListIntKey blik = new BooleanListIntKey((byte) 1); + final BooleanContainer booleanContainerInt = new BooleanContainerBuilder() + .setBooleanListInt(Collections.singletonMap(blik, new BooleanListIntBuilder() + .withKey(blik) .setBooleanLeafInt((byte) 1) .build())) .build(); diff --git a/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/test/CachingCodecTest.java b/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/test/CachingCodecTest.java index 6768bef5b7..7c8fa7a729 100644 --- a/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/test/CachingCodecTest.java +++ b/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/test/CachingCodecTest.java @@ -14,10 +14,10 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; -import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import java.util.Collection; -import java.util.List; +import java.util.Map; import org.junit.Before; import org.junit.Test; import org.opendaylight.mdsal.binding.dom.codec.api.BindingDataObjectCodecTreeNode; @@ -47,8 +47,8 @@ public class CachingCodecTest extends AbstractBindingCodecTest { private static final NodeIdentifier TOP_LEVEL_LIST_ARG = new NodeIdentifier(TopLevelList.QNAME); private static final InstanceIdentifier TOP_PATH = InstanceIdentifier.create(Top.class); - private static final List TWO_LIST = createList(2); - private static final List THREE_LIST = createList(3); + private static final Map TWO_LIST = createList(2); + private static final Map THREE_LIST = createList(3); private static final Top TOP_TWO_LIST_DATA = new TopBuilder().setTopLevelList(TWO_LIST).build(); private static final Top TOP_THREE_LIST_DATA = new TopBuilder().setTopLevelList(THREE_LIST).build(); @@ -77,12 +77,11 @@ public class CachingCodecTest extends AbstractBindingCodecTest { contNode = registry.getCodecContext().getSubtreeCodec(CONT_PATH); } - private static List createList(final int num) { - - final ImmutableList.Builder builder = ImmutableList.builder(); + private static Map createList(final int num) { + final ImmutableMap.Builder builder = ImmutableMap.builder(); for (int i = 0; i < num; i++) { final TopLevelListKey key = new TopLevelListKey("test-" + i); - builder.add(new TopLevelListBuilder().withKey(key).build()); + builder.put(key, new TopLevelListBuilder().withKey(key).build()); } return builder.build(); } @@ -134,7 +133,7 @@ public class CachingCodecTest extends AbstractBindingCodecTest { final Top input = new TopBuilder().build(); assertNull(input.getTopLevelList()); - assertEquals(ImmutableList.of(), input.nonnullTopLevelList()); + assertEquals(ImmutableMap.of(), input.nonnullTopLevelList()); final NormalizedNode dom = cachingCodec.serialize(input); final Top output = cachingCodec.deserialize(dom); @@ -142,7 +141,7 @@ public class CachingCodecTest extends AbstractBindingCodecTest { assertTrue(output.equals(input)); assertNull(output.getTopLevelList()); - assertEquals(ImmutableList.of(), output.nonnullTopLevelList()); + assertEquals(ImmutableMap.of(), output.nonnullTopLevelList()); } @SafeVarargs diff --git a/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/test/CaseSubstitutionTest.java b/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/test/CaseSubstitutionTest.java index d379eb1090..c7ed608f8b 100644 --- a/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/test/CaseSubstitutionTest.java +++ b/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/test/CaseSubstitutionTest.java @@ -60,11 +60,8 @@ public class CaseSubstitutionTest extends AbstractBindingCodecTest { private static RpcComplexUsesAugment createComplexData() { return new RpcComplexUsesAugmentBuilder() - .setContainerWithUses(new ContainerWithUsesBuilder() - .setLeafFromGrouping("foo") - .build()) - .setListViaUses(Collections.emptyList()) - .build(); + .setContainerWithUses(new ContainerWithUsesBuilder().setLeafFromGrouping("foo").build()) + .setListViaUses(Collections.emptyMap()) + .build(); } - } diff --git a/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/test/EmptyLeafTest.java b/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/test/EmptyLeafTest.java index 6450a29c9f..c44141791d 100644 --- a/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/test/EmptyLeafTest.java +++ b/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/test/EmptyLeafTest.java @@ -58,13 +58,11 @@ public class EmptyLeafTest extends AbstractBindingCodecTest { assertNotNull(((EmptyLeaf) list).getEmptyType()); } + // FIXME: either remove this method or take advantage of it private static RpcComplexUsesAugment createComplexData() { return new RpcComplexUsesAugmentBuilder() - .setContainerWithUses(new ContainerWithUsesBuilder() - .setLeafFromGrouping("foo") - .build()) - .setListViaUses(Collections.emptyList()) - .build(); + .setContainerWithUses(new ContainerWithUsesBuilder().setLeafFromGrouping("foo").build()) + .setListViaUses(Collections.emptyMap()) + .build(); } - } diff --git a/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/test/KeyInheritenceTest.java b/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/test/KeyInheritenceTest.java index 542d79b567..f9e50ef824 100644 --- a/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/test/KeyInheritenceTest.java +++ b/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/test/KeyInheritenceTest.java @@ -9,7 +9,7 @@ package org.opendaylight.mdsal.binding.dom.codec.test; import static org.junit.Assert.assertEquals; -import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import java.util.Map.Entry; import org.junit.Test; import org.opendaylight.yang.gen.v1.mdsal442.keydef.norev.Def; @@ -29,10 +29,10 @@ public class KeyInheritenceTest extends AbstractBindingCodecTest { private static final InstanceIdentifier USE_IID = InstanceIdentifier.create(Use.class); private static final Def DEF = new DefBuilder() - .setLst(ImmutableList.of(new LstBuilder().setFoo("foo").withKey(KEY).build())) + .setLst(ImmutableMap.of(KEY, new LstBuilder().setFoo("foo").withKey(KEY).build())) .build(); private static final Use USE = new UseBuilder() - .setLst(ImmutableList.of(new LstBuilder().setFoo("foo").withKey(KEY).build())) + .setLst(ImmutableMap.of(KEY, new LstBuilder().setFoo("foo").withKey(KEY).build())) .build(); @Test diff --git a/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/test/NormalizedNodeSerializeDeserializeTest.java b/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/test/NormalizedNodeSerializeDeserializeTest.java index 731ce67c70..81a54d15ce 100644 --- a/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/test/NormalizedNodeSerializeDeserializeTest.java +++ b/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/test/NormalizedNodeSerializeDeserializeTest.java @@ -230,7 +230,7 @@ public class NormalizedNodeSerializeDeserializeTest extends AbstractBindingCodec for (Entry>, ? extends Augmentation> augment : augments.entrySet()) { topBuilder.addAugmentation(augment.getKey(), augment.getValue()); } - return topBuilder.setTopLevelList(Collections.emptyList()).build(); + return topBuilder.setTopLevelList(Collections.emptyMap()).build(); } @Test diff --git a/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/test/NotificationProcessingTest.java b/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/test/NotificationProcessingTest.java index 5a8e14daf9..ce2cad9697 100644 --- a/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/test/NotificationProcessingTest.java +++ b/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/test/NotificationProcessingTest.java @@ -10,7 +10,7 @@ package org.opendaylight.mdsal.binding.dom.codec.test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import java.time.Instant; import org.junit.Test; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.TwoLevelListChanged; @@ -31,9 +31,9 @@ public class NotificationProcessingTest extends AbstractBindingCodecTest { private static final QName NAME = QName.create(TopLevelList.QNAME, "name"); private static TwoLevelListChanged createTestBindingData() { + final TopLevelListKey key = new TopLevelListKey("test"); return new TwoLevelListChangedBuilder() - .setTopLevelList(ImmutableList.of( - new TopLevelListBuilder().withKey(new TopLevelListKey("test")).build())) + .setTopLevelList(ImmutableMap.of(key, new TopLevelListBuilder().withKey(key).build())) .build(); } diff --git a/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/test/RpcDataSerializationTest.java b/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/test/RpcDataSerializationTest.java index 79103528ce..ef777b521e 100644 --- a/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/test/RpcDataSerializationTest.java +++ b/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/test/RpcDataSerializationTest.java @@ -10,7 +10,7 @@ package org.opendaylight.mdsal.binding.dom.codec.test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import org.junit.Test; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.GetTopOutput; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.GetTopOutputBuilder; @@ -31,11 +31,13 @@ public class RpcDataSerializationTest extends AbstractBindingCodecTest { private static final SchemaPath PUT_TOP_INPUT = SchemaPath.create(true, PUT_TOP, PutTopInput.QNAME); private static final SchemaPath GET_TOP_OUTPUT = SchemaPath.create(true, GET_TOP, GetTopOutput.QNAME); + private static final TopLevelListKey LIST_KEY = new TopLevelListKey("test"); + @Test public void testRpcInputToNormalized() { - final PutTopInputBuilder tb = new PutTopInputBuilder(); - tb.setTopLevelList(ImmutableList.of(new TopLevelListBuilder().withKey(new TopLevelListKey("test")).build())); - final PutTopInput bindingOriginal = tb.build(); + final PutTopInput bindingOriginal = new PutTopInputBuilder() + .setTopLevelList(ImmutableMap.of(LIST_KEY, new TopLevelListBuilder().withKey(LIST_KEY).build())) + .build(); final ContainerNode dom = registry.toNormalizedNodeRpcData(bindingOriginal); assertNotNull(dom); assertEquals(PutTopInput.QNAME, dom.getIdentifier().getNodeType()); @@ -46,16 +48,14 @@ public class RpcDataSerializationTest extends AbstractBindingCodecTest { @Test public void testRpcOutputToNormalized() { - final GetTopOutputBuilder tb = new GetTopOutputBuilder(); - tb.setTopLevelList(ImmutableList.of(new TopLevelListBuilder().withKey(new TopLevelListKey("test")).build())); - final GetTopOutput bindingOriginal = tb.build(); + final GetTopOutput bindingOriginal = new GetTopOutputBuilder() + .setTopLevelList(ImmutableMap.of(LIST_KEY, new TopLevelListBuilder().withKey(LIST_KEY).build())) + .build(); final ContainerNode dom = registry.toNormalizedNodeRpcData(bindingOriginal); assertNotNull(dom); assertEquals(GetTopOutput.QNAME, dom.getIdentifier().getNodeType()); final DataObject bindingDeserialized = registry.fromNormalizedNodeRpcData(GET_TOP_OUTPUT, dom); assertEquals(bindingOriginal, bindingDeserialized); - } - } diff --git a/binding/mdsal-binding-generator-impl/src/main/java/org/opendaylight/mdsal/binding/generator/impl/AbstractTypeGenerator.java b/binding/mdsal-binding-generator-impl/src/main/java/org/opendaylight/mdsal/binding/generator/impl/AbstractTypeGenerator.java index 1f3af42563..f5806f6e0f 100644 --- a/binding/mdsal-binding-generator-impl/src/main/java/org/opendaylight/mdsal/binding/generator/impl/AbstractTypeGenerator.java +++ b/binding/mdsal-binding-generator-impl/src/main/java/org/opendaylight/mdsal/binding/generator/impl/AbstractTypeGenerator.java @@ -40,6 +40,7 @@ import static org.opendaylight.mdsal.binding.model.util.Types.augmentationTypeFo import static org.opendaylight.mdsal.binding.model.util.Types.classType; import static org.opendaylight.mdsal.binding.model.util.Types.listTypeFor; import static org.opendaylight.mdsal.binding.model.util.Types.listenableFutureTypeFor; +import static org.opendaylight.mdsal.binding.model.util.Types.mapTypeFor; import static org.opendaylight.mdsal.binding.model.util.Types.primitiveVoidType; import static org.opendaylight.mdsal.binding.model.util.Types.typeForClass; import static org.opendaylight.mdsal.binding.model.util.Types.wildcardTypeFor; @@ -325,7 +326,14 @@ abstract class AbstractTypeGenerator { keyTypeBuilder = null; } - final ParameterizedType listType = listTypeFor(genType); + // Decide whether to generate a List or a Map + final ParameterizedType listType; + if (keyTypeBuilder != null && !node.isUserOrdered()) { + listType = mapTypeFor(keyTypeBuilder, genType); + } else { + listType = listTypeFor(genType); + } + constructGetter(parent, listType, node); constructNonnull(parent, listType, node); diff --git a/binding/mdsal-binding-generator-impl/src/test/java/org/opendaylight/mdsal/binding/generator/impl/ChoiceCaseGenTypesTest.java b/binding/mdsal-binding-generator-impl/src/test/java/org/opendaylight/mdsal/binding/generator/impl/ChoiceCaseGenTypesTest.java index 93a7e1dc5c..935b8d339a 100644 --- a/binding/mdsal-binding-generator-impl/src/test/java/org/opendaylight/mdsal/binding/generator/impl/ChoiceCaseGenTypesTest.java +++ b/binding/mdsal-binding-generator-impl/src/test/java/org/opendaylight/mdsal/binding/generator/impl/ChoiceCaseGenTypesTest.java @@ -76,7 +76,7 @@ public class ChoiceCaseGenTypesTest extends AbstractTypesTest { containsInterface("LockType", genType); genType = checkGeneratedType(genTypes, "PartialLock", pcgPref + ".lock.type"); // case - containsMethods(genType, new NameTypePattern("getPartialLock", "List")); + containsMethods(genType, new NameTypePattern("getPartialLock", "Map")); containsInterface("LockType", genType); genType = checkGeneratedType(genTypes, "Fingerprint", pcgPref + ".lock.type"); // case @@ -159,7 +159,7 @@ public class ChoiceCaseGenTypesTest extends AbstractTypesTest { genType = checkGeneratedType(genTypes, "UnknownFiles", pcgPref + ".netconf.state.datastores.datastore.storage.format"); // case - containsMethods(genType, new NameTypePattern("getFiles", "List")); + containsMethods(genType, new NameTypePattern("getFiles", "Map")); containsInterface("StorageFormat", genType); // case diff --git a/binding/mdsal-binding-generator-util/src/main/java/org/opendaylight/mdsal/binding/model/util/Types.java b/binding/mdsal-binding-generator-util/src/main/java/org/opendaylight/mdsal/binding/model/util/Types.java index 2dec3dae45..9f7351e9d0 100644 --- a/binding/mdsal-binding-generator-util/src/main/java/org/opendaylight/mdsal/binding/model/util/Types.java +++ b/binding/mdsal-binding-generator-util/src/main/java/org/opendaylight/mdsal/binding/model/util/Types.java @@ -156,6 +156,14 @@ public final class Types { return parameterizedTypeFor(MAP_TYPE, keyType, valueType); } + public static boolean isMapType(final ParameterizedType type) { + return MAP_TYPE.equals(type.getRawType()); + } + + public static boolean isMapType(final Type type) { + return type instanceof ParameterizedType && isMapType((ParameterizedType) type); + } + /** * Returns an instance of {@link ParameterizedType} describing the typed {@link Set}<V> with concrete type * of value. diff --git a/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/BuilderTemplate.xtend b/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/BuilderTemplate.xtend index 6a2d788889..0194697f14 100644 --- a/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/BuilderTemplate.xtend +++ b/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/BuilderTemplate.xtend @@ -275,13 +275,15 @@ class BuilderTemplate extends AbstractBuilderTemplate { val returnType = field.returnType if (returnType instanceof ParameterizedType) { if (Types.isListType(returnType)) { - return generateListSetter(field, returnType.actualTypeArguments.get(0)) + return generateListSetter(field, returnType.actualTypeArguments.get(0), "") + } else if (Types.isMapType(returnType)) { + return generateListSetter(field, returnType.actualTypeArguments.get(1), ".values()") } } return generateSimpleSetter(field, returnType) } - def private generateListSetter(GeneratedProperty field, Type actualType) ''' + def private generateListSetter(GeneratedProperty field, Type actualType, String extractor) ''' «val restrictions = restrictionsForSetter(actualType)» «IF restrictions !== null» «generateCheckers(field, restrictions, actualType)» @@ -289,7 +291,7 @@ class BuilderTemplate extends AbstractBuilderTemplate { public «type.getName» set«field.getName.toFirstUpper»(final «field.returnType.importedName» values) { «IF restrictions !== null» if (values != null) { - for («actualType.importedName» value : values) { + for («actualType.importedName» value : values«extractor») { «checkArgument(field, restrictions, actualType, "value")» } } diff --git a/binding/mdsal-binding-test-model/src/main/java/org/opendaylight/mdsal/binding/test/model/util/ListsBindingUtils.java b/binding/mdsal-binding-test-model/src/main/java/org/opendaylight/mdsal/binding/test/model/util/ListsBindingUtils.java index 7ac0e9cccf..25796a5861 100644 --- a/binding/mdsal-binding-test-model/src/main/java/org/opendaylight/mdsal/binding/test/model/util/ListsBindingUtils.java +++ b/binding/mdsal-binding-test-model/src/main/java/org/opendaylight/mdsal/binding/test/model/util/ListsBindingUtils.java @@ -7,7 +7,8 @@ */ package org.opendaylight.mdsal.binding.test.model.util; -import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; import java.util.Arrays; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.augment.rev140709.TreeComplexUsesAugment; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.augment.rev140709.TreeComplexUsesAugmentBuilder; @@ -59,7 +60,7 @@ public final class ListsBindingUtils { } public static Top top(final TopLevelList... listItems) { - return new TopBuilder().setTopLevelList(Arrays.asList(listItems)).build(); + return new TopBuilder().setTopLevelList(Maps.uniqueIndex(Arrays.asList(listItems), TopLevelList::key)).build(); } public static TopLevelList topLevelList(final TopLevelListKey key) { @@ -71,9 +72,9 @@ public final class ListsBindingUtils { } public static TreeComplexUsesAugment complexUsesAugment(final ListViaUsesKey... keys) { - final ImmutableList.Builder listViaUses = ImmutableList.builder(); + final ImmutableMap.Builder listViaUses = ImmutableMap.builder(); for (final ListViaUsesKey key : keys) { - listViaUses.add(new ListViaUsesBuilder().withKey(key).build()); + listViaUses.put(key, new ListViaUsesBuilder().withKey(key).build()); } return new TreeComplexUsesAugmentBuilder().setListViaUses(listViaUses.build()).build(); } diff --git a/binding/mdsal-binding-test-utils/src/test/java/org/opendaylight/mdsal/binding/testutils/AssertDataObjectsTest.java b/binding/mdsal-binding-test-utils/src/test/java/org/opendaylight/mdsal/binding/testutils/AssertDataObjectsTest.java index 40fd5c217e..bb8be68626 100644 --- a/binding/mdsal-binding-test-utils/src/test/java/org/opendaylight/mdsal/binding/testutils/AssertDataObjectsTest.java +++ b/binding/mdsal-binding-test-utils/src/test/java/org/opendaylight/mdsal/binding/testutils/AssertDataObjectsTest.java @@ -9,7 +9,7 @@ package org.opendaylight.mdsal.binding.testutils; import static org.opendaylight.mdsal.common.api.LogicalDatastoreType.OPERATIONAL; -import java.util.Map; +import java.util.Map.Entry; import org.junit.Test; import org.opendaylight.mdsal.binding.api.ReadTransaction; import org.opendaylight.mdsal.binding.api.WriteTransaction; @@ -43,8 +43,8 @@ public class AssertDataObjectsTest extends AbstractDataBrokerTest { @Test public void testAssertDataObjectsWithComplexTopWithKey() { AssertDataObjects.assertEqualByText(HEADER + "new TopBuilder >> [\n" - + " topLevelList = #[\n" - + " new TopLevelListBuilder >> [\n" + + " topLevelList = #{\n" + + " new TopLevelListKey(\"foo\") -> new TopLevelListBuilder >> [\n" + " name = \"foo\"\n" + " addAugmentation(TreeComplexUsesAugment, new TreeComplexUsesAugmentBuilder >> [\n" + " containerWithUses = new ContainerWithUsesBuilder >> [\n" @@ -52,7 +52,7 @@ public class AssertDataObjectsTest extends AbstractDataBrokerTest { + " ]\n" + " ])\n" + " ]\n" - + " ]\n" + + " }\n" + "]", ExpectedObjects.top()); } @@ -86,8 +86,8 @@ public class AssertDataObjectsTest extends AbstractDataBrokerTest { String expectedTopText = "import static extension org.opendaylight.mdsal.binding.testutils." + "XtendBuilderExtensions.operator_doubleGreaterThan\n\n" + "new TopBuilder >> [\n" - + " topLevelList = #[\n" - + " new TopLevelListBuilder >> [\n" + + " topLevelList = #{\n" + + " new TopLevelListKey(\"foo\") -> new TopLevelListBuilder >> [\n" + " name = \"foo\"\n" + " addAugmentation(TreeComplexUsesAugment, new TreeComplexUsesAugmentBuilder >> [\n" + " containerWithUses = new ContainerWithUsesBuilder >> [\n" @@ -95,13 +95,13 @@ public class AssertDataObjectsTest extends AbstractDataBrokerTest { + " ]\n" + " ])\n" + " ]\n" - + " ]\n" + + " }\n" + "]"; AssertDataObjects.assertEqualByText(expectedTopText, actualTop); } void put(WriteTransaction tx, LogicalDatastoreType store, - Map.Entry, T> obj) { + Entry, T> obj) { tx.put(OPERATIONAL, obj.getKey(), obj.getValue()); } diff --git a/binding/mdsal-binding-test-utils/src/test/java/org/opendaylight/mdsal/binding/testutils/AugmentableExtensionTest.java b/binding/mdsal-binding-test-utils/src/test/java/org/opendaylight/mdsal/binding/testutils/AugmentableExtensionTest.java index e2ed4a4d84..cd3e399104 100644 --- a/binding/mdsal-binding-test-utils/src/test/java/org/opendaylight/mdsal/binding/testutils/AugmentableExtensionTest.java +++ b/binding/mdsal-binding-test-utils/src/test/java/org/opendaylight/mdsal/binding/testutils/AugmentableExtensionTest.java @@ -57,7 +57,7 @@ public class AugmentableExtensionTest extends AbstractDataBrokerTest { Top actualTop = readTx.read(OPERATIONAL, id).get().get(); AssertBeans.assertEqualByText("#{\n}", augmentableExtension.getAugmentations(actualTop)); - TopLevelList topLevelList = actualTop.getTopLevelList().get(0); + TopLevelList topLevelList = actualTop.getTopLevelList().values().iterator().next(); AssertDataObjects.assertEqualByText("#{\n" + " TreeComplexUsesAugment -> new TreeComplexUsesAugmentBuilder >> [\n" + " containerWithUses = new ContainerWithUsesBuilder >> [\n" diff --git a/binding/mdsal-binding-test-utils/src/test/java/org/opendaylight/mdsal/binding/testutils/ExpectedObjects.java b/binding/mdsal-binding-test-utils/src/test/java/org/opendaylight/mdsal/binding/testutils/ExpectedObjects.java index be384e90e3..f673303b04 100644 --- a/binding/mdsal-binding-test-utils/src/test/java/org/opendaylight/mdsal/binding/testutils/ExpectedObjects.java +++ b/binding/mdsal-binding-test-utils/src/test/java/org/opendaylight/mdsal/binding/testutils/ExpectedObjects.java @@ -7,6 +7,7 @@ */ package org.opendaylight.mdsal.binding.testutils; +import com.google.common.collect.Maps; import java.util.Collections; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.augment.rev140709.TreeComplexUsesAugment; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.augment.rev140709.TreeComplexUsesAugmentBuilder; @@ -47,12 +48,12 @@ public final class ExpectedObjects { public static Top top() { return new TopBuilder() - .setTopLevelList(Collections.singletonList(new TopLevelListBuilder() + .setTopLevelList(Maps.uniqueIndex(Collections.singletonList(new TopLevelListBuilder() .setName("foo") .addAugmentation(TreeComplexUsesAugment.class, new TreeComplexUsesAugmentBuilder() .setContainerWithUses(new ContainerWithUsesBuilder().setLeafFromGrouping("foo").build()) .build()) - .build())) + .build()), TopLevelList::key)) .build(); } } diff --git a/yanglib/mdsal-yanglib-rfc7895/src/main/java/org/opendaylight/mdsal/yanglib/rfc7895/MountPointContextFactoryImpl.java b/yanglib/mdsal-yanglib-rfc7895/src/main/java/org/opendaylight/mdsal/yanglib/rfc7895/MountPointContextFactoryImpl.java index a0262b557e..b03f237f91 100644 --- a/yanglib/mdsal-yanglib-rfc7895/src/main/java/org/opendaylight/mdsal/yanglib/rfc7895/MountPointContextFactoryImpl.java +++ b/yanglib/mdsal-yanglib-rfc7895/src/main/java/org/opendaylight/mdsal/yanglib/rfc7895/MountPointContextFactoryImpl.java @@ -86,7 +86,7 @@ final class MountPointContextFactoryImpl extends AbstractMountPointContextFactor final List requiredSources = new ArrayList<>(); final List librarySources = new ArrayList<>(); - for (Module module : modState.nonnullModule()) { + for (Module module : modState.nonnullModule().values()) { final SourceReference modRef = sourceRefFor(module, module.getSchema()); // TODO: take deviations/features into account @@ -97,7 +97,7 @@ final class MountPointContextFactoryImpl extends AbstractMountPointContextFactor requiredSources.add(modRef); } - for (Submodule submodule : module.nonnullSubmodule()) { + for (Submodule submodule : module.nonnullSubmodule().values()) { // Submodules go to library, as they are pulled in as needed librarySources.add(sourceRefFor(submodule, submodule.getSchema())); } diff --git a/yanglib/mdsal-yanglib-rfc8525/src/main/java/org/opendaylight/mdsal/yanglib/rfc8525/MountPointContextFactoryImpl.java b/yanglib/mdsal-yanglib-rfc8525/src/main/java/org/opendaylight/mdsal/yanglib/rfc8525/MountPointContextFactoryImpl.java index 3c1cd113ee..d293baa69d 100644 --- a/yanglib/mdsal-yanglib-rfc8525/src/main/java/org/opendaylight/mdsal/yanglib/rfc8525/MountPointContextFactoryImpl.java +++ b/yanglib/mdsal-yanglib-rfc8525/src/main/java/org/opendaylight/mdsal/yanglib/rfc8525/MountPointContextFactoryImpl.java @@ -17,6 +17,7 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Optional; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; @@ -36,8 +37,10 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.librar import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.module.set.parameters.ImportOnlyModuleRevisionBuilder; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.module.set.parameters.Module; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.yang.library.parameters.Datastore; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.yang.library.parameters.DatastoreKey; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.yang.library.parameters.ModuleSet; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.yang.library.parameters.Schema; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.yang.library.parameters.SchemaKey; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.YangIdentifier; import org.opendaylight.yangtools.rcf8528.data.util.AbstractMountPointContextFactory; import org.opendaylight.yangtools.rfc8528.data.api.MountPointContextFactory; @@ -109,13 +112,13 @@ final class MountPointContextFactoryImpl extends AbstractMountPointContextFactor } private @NonNull SchemaContext bindLibrary(final @NonNull YangLibrary yangLib) throws YangParserException { - final List datastores = yangLib.nonnullDatastore(); + final Map datastores = yangLib.nonnullDatastore(); checkArgument(!datastores.isEmpty(), "No datastore defined"); final List requiredSources = new ArrayList<>(); final List librarySources = new ArrayList<>(); final HashSet moduleSet = findModuleSet(yangLib, findSchemaName(datastores, Operational.QNAME)); - for (ModuleSet modSet : yangLib.nonnullModuleSet()) { + for (ModuleSet modSet : yangLib.nonnullModuleSet().values()) { if (moduleSet.remove(modSet.getName())) { fillModules(librarySources, requiredSources, modSet); } @@ -131,7 +134,7 @@ final class MountPointContextFactoryImpl extends AbstractMountPointContextFactor final List librarySources = new ArrayList<>(); for (org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.module.list - .Module module : modState.nonnullModule()) { + .Module module : modState.nonnullModule().values()) { final SourceReference modRef = sourceRefFor(module, module.getSchema()); // TODO: take deviations/features into account @@ -143,7 +146,7 @@ final class MountPointContextFactoryImpl extends AbstractMountPointContextFactor } for (org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.module.list - .module.Submodule submodule : module.nonnullSubmodule()) { + .module.Submodule submodule : module.nonnullSubmodule().values()) { // Submodules go to library, as they are pulled in as needed librarySources.add(sourceRefFor(submodule, submodule.getSchema())); } @@ -152,8 +155,8 @@ final class MountPointContextFactoryImpl extends AbstractMountPointContextFactor return resolver.resolveSchemaContext(librarySources, requiredSources); } - private String findSchemaName(final List datastores, final QName qname) { - final Iterator it = datastores.iterator(); + private String findSchemaName(final Map datastores, final QName qname) { + final Iterator it = datastores.values().iterator(); final Datastore ds = it.next(); // FIXME: This is ugly, but it is the most compatible thing we can do without knowing the exact requested @@ -186,28 +189,27 @@ final class MountPointContextFactoryImpl extends AbstractMountPointContextFactor } private static HashSet findModuleSet(final YangLibrary yangLib, final String schemaName) { - for (Schema schema : yangLib.nonnullSchema()) { - if (schemaName.equals(schema.getName())) { - return new HashSet<>(schema.getModuleSet()); - } + final Schema schema = yangLib.nonnullSchema().get(new SchemaKey(schemaName)); + if (schema == null) { + throw new IllegalArgumentException("Failed to find moduleSet for " + schemaName); } - throw new IllegalArgumentException("Failed to find moduleSet for " + schemaName); + return new HashSet<>(schema.getModuleSet()); } private static void fillModules(final List librarySources, final List requiredSources, final ModuleSet modSet) { // TODO: take deviations/features into account - for (ImportOnlyModule mod : modSet.nonnullImportOnlyModule()) { + for (ImportOnlyModule mod : modSet.nonnullImportOnlyModule().values()) { fillSource(librarySources, mod.getName(), ImportOnlyModuleRevisionBuilder.toYangCommon(mod.getRevision()), mod.getLocation()); - mod.nonnullSubmodule().forEach(sub -> { + mod.nonnullSubmodule().values().forEach(sub -> { fillSource(librarySources, sub.getName(), toYangCommon(sub.getRevision()), sub.getLocation()); }); } - for (Module mod : modSet.nonnullModule()) { + for (Module mod : modSet.nonnullModule().values()) { fillSource(requiredSources, mod.getName(), toYangCommon(mod.getRevision()), mod.getLocation()); - mod.nonnullSubmodule().forEach(sub -> { + mod.nonnullSubmodule().values().forEach(sub -> { fillSource(librarySources, sub.getName(), toYangCommon(sub.getRevision()), sub.getLocation()); }); } -- 2.36.6