Remove MapModificationStrategy hack 50/80150/6
authorRobert Varga <robert.varga@pantheon.tech>
Tue, 5 Feb 2019 02:07:37 +0000 (03:07 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Tue, 5 Feb 2019 14:12:51 +0000 (15:12 +0100)
MapModificationStrategy has special handling to deal with DataTrees
rooted at a MapEntryNode, which really papered over failure of
InMemoryDataTree to properly resolve its root strategy.

Fix up InMemoryDataTree to use ListEntryModificationStrategy instead
of MapModificationStrategy when it is rooted at a particular map
entry.

JIRA: YANGTOOLS-951
Change-Id: I2e0306d1bf88fcee517a32c5903dfa98c287eb2c
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/AugmentationModificationStrategy.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/ChoiceModificationStrategy.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/ContainerModificationStrategy.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/InMemoryDataTree.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/LeafSetModificationStrategy.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/ListEntryModificationStrategy.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/MapModificationStrategy.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/NormalizedNodeContainerSupport.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/UnkeyedListModificationStrategy.java
yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/MapEntryRootTest.java [new file with mode: 0644]

index 1edfb16e8caa5947b0b417278c679ad714da5c2a..1664effa6f1ab126f6d0ef1330766d6711a93654 100644 (file)
@@ -16,7 +16,6 @@ import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.Version;
 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableAugmentationNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.tree.NormalizedNodeContainerSupport.Single;
 import org.opendaylight.yangtools.yang.data.util.DataSchemaContextNode;
 import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
@@ -24,8 +23,9 @@ import org.opendaylight.yangtools.yang.model.util.EffectiveAugmentationSchema;
 
 final class AugmentationModificationStrategy
         extends DataNodeContainerModificationStrategy<AugmentationSchemaNode> {
-    private static final Single<AugmentationIdentifier, AugmentationNode> SUPPORT = new Single<>(AugmentationNode.class,
-            ImmutableAugmentationNodeBuilder::create, ImmutableAugmentationNodeBuilder::create);
+    private static final NormalizedNodeContainerSupport<AugmentationIdentifier, AugmentationNode> SUPPORT =
+            new NormalizedNodeContainerSupport<>(AugmentationNode.class, ImmutableAugmentationNodeBuilder::create,
+                    ImmutableAugmentationNodeBuilder::create);
 
     private final AugmentationNode emptyNode;
 
index 6c11afe73832192c1bdd47d232abe655093d5077..a03c21e7e8b5917e6f18503b365fbc41bf0d56ab 100644 (file)
@@ -32,15 +32,15 @@ import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.Version;
 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableChoiceNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.tree.NormalizedNodeContainerSupport.Single;
 import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.CaseSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 
 final class ChoiceModificationStrategy extends AbstractNodeContainerModificationStrategy {
-    private static final Single<NodeIdentifier, ChoiceNode> SUPPORT = new Single<>(ChoiceNode.class,
-            ImmutableChoiceNodeBuilder::create, ImmutableChoiceNodeBuilder::create);
+    private static final NormalizedNodeContainerSupport<NodeIdentifier, ChoiceNode> SUPPORT =
+            new NormalizedNodeContainerSupport<>(ChoiceNode.class, ImmutableChoiceNodeBuilder::create,
+                    ImmutableChoiceNodeBuilder::create);
 
     private final ImmutableMap<PathArgument, ModificationApplyOperation> childNodes;
     // FIXME: enforce leaves not coming from two case statements at the same time
index 79d4f39a0315577e066554112b0544d76212ae35..821625f9f6868a87a86ed8a5a0a5b8c336de7e90 100644 (file)
@@ -17,7 +17,6 @@ import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeConfiguratio
 import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.Version;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.tree.NormalizedNodeContainerSupport.Single;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 
 /**
@@ -65,8 +64,9 @@ class ContainerModificationStrategy extends DataNodeContainerModificationStrateg
         }
     }
 
-    private static final Single<NodeIdentifier, ContainerNode> SUPPORT = new Single<>(ContainerNode.class,
-            ImmutableContainerNodeBuilder::create, ImmutableContainerNodeBuilder::create);
+    private static final NormalizedNodeContainerSupport<NodeIdentifier, ContainerNode> SUPPORT =
+            new NormalizedNodeContainerSupport<>(ContainerNode.class, ImmutableContainerNodeBuilder::create,
+                    ImmutableContainerNodeBuilder::create);
 
     ContainerModificationStrategy(final ContainerSchemaNode schemaNode, final DataTreeConfiguration treeConfig) {
         super(SUPPORT, schemaNode, treeConfig);
index 043cdc2ba1b2f640183de7ea0a289ca73d18a8f9..e3576f748118a7b27a5cb948715ded02885ce498 100644 (file)
@@ -14,6 +14,8 @@ import com.google.common.base.MoreObjects;
 import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
 import javax.annotation.Nonnull;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate;
@@ -24,6 +26,7 @@ import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -63,9 +66,16 @@ final class InMemoryDataTree extends AbstractDataTreeTip implements DataTree {
     }
 
     private ModificationApplyOperation getOperation(final DataSchemaNode rootSchemaNode) {
-        if (maskMandatory && rootSchemaNode instanceof ContainerSchemaNode) {
+        if (rootSchemaNode instanceof ContainerSchemaNode && maskMandatory) {
             return new ContainerModificationStrategy((ContainerSchemaNode) rootSchemaNode, treeConfig);
         }
+        if (rootSchemaNode instanceof ListSchemaNode) {
+            final PathArgument arg = treeConfig.getRootPath().getLastPathArgument();
+            if (arg instanceof NodeIdentifierWithPredicates) {
+                return maskMandatory ? new ListEntryModificationStrategy((ListSchemaNode) rootSchemaNode, treeConfig)
+                        : ListEntryModificationStrategy.of((ListSchemaNode) rootSchemaNode, treeConfig);
+            }
+        }
 
         return SchemaAwareApplyOperation.from(rootSchemaNode, treeConfig);
     }
index 4a1a393bbd5e4d0b230a8ca0da310f40173e9560..69fe07e764e044d23010eee89515d671dd49c447 100644 (file)
@@ -17,18 +17,17 @@ import org.opendaylight.yangtools.yang.data.api.schema.OrderedLeafSetNode;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeConfiguration;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedLeafSetNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.tree.NormalizedNodeContainerSupport.Single;
 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
 
 final class LeafSetModificationStrategy extends AbstractNodeContainerModificationStrategy {
     @SuppressWarnings({ "unchecked", "rawtypes" })
-    private static final Single<NodeIdentifier, OrderedLeafSetNode<?>> ORDERED_SUPPORT =
-            new Single(OrderedLeafSetNode.class, ChildTrackingPolicy.ORDERED,
+    private static final NormalizedNodeContainerSupport<NodeIdentifier, OrderedLeafSetNode<?>> ORDERED_SUPPORT =
+            new NormalizedNodeContainerSupport(OrderedLeafSetNode.class, ChildTrackingPolicy.ORDERED,
                 foo -> ImmutableOrderedLeafSetNodeBuilder.create((OrderedLeafSetNode<?>)foo),
                 ImmutableOrderedLeafSetNodeBuilder::create);
     @SuppressWarnings({ "unchecked", "rawtypes" })
-    private static final Single<NodeIdentifier, LeafSetNode<?>> UNORDERED_SUPPORT =
-            new Single(LeafSetNode.class,
+    private static final NormalizedNodeContainerSupport<NodeIdentifier, LeafSetNode<?>> UNORDERED_SUPPORT =
+            new NormalizedNodeContainerSupport(LeafSetNode.class,
                 foo -> ImmutableLeafSetNodeBuilder.create((LeafSetNode<?>)foo),
                 ImmutableLeafSetNodeBuilder::create);
 
index d1042d5f8d0b04f7a72ec3fe0ca097cdec97a155..825a77ddedab8394d332b95ca8b6a9517dbfd3d2 100644 (file)
@@ -17,7 +17,6 @@ import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeConfiguratio
 import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.Version;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.tree.NormalizedNodeContainerSupport.Single;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 
 class ListEntryModificationStrategy extends DataNodeContainerModificationStrategy<ListSchemaNode> {
@@ -60,8 +59,9 @@ class ListEntryModificationStrategy extends DataNodeContainerModificationStrateg
         }
     }
 
-    private static final Single<NodeIdentifierWithPredicates, MapEntryNode> SUPPORT = new Single<>(MapEntryNode.class,
-            ImmutableMapEntryNodeBuilder::create, ImmutableMapEntryNodeBuilder::create);
+    private static final NormalizedNodeContainerSupport<NodeIdentifierWithPredicates, MapEntryNode> SUPPORT =
+            new NormalizedNodeContainerSupport<>(MapEntryNode.class, ImmutableMapEntryNodeBuilder::create,
+                    ImmutableMapEntryNodeBuilder::create);
 
     ListEntryModificationStrategy(final ListSchemaNode schema, final DataTreeConfiguration treeConfig) {
         super(SUPPORT, schema, treeConfig);
index 2cfeeaa471b78c16c4d5947c35e31b0be7ec5505..ae65ef8a827ecd96504ded9248bc019319aba497 100644 (file)
@@ -12,6 +12,7 @@ import static java.util.Objects.requireNonNull;
 import com.google.common.base.MoreObjects.ToStringHelper;
 import java.util.Optional;
 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.schema.MapNode;
 import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode;
@@ -22,20 +23,20 @@ import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.Version;
 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedMapNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.tree.NormalizedNodeContainerSupport.MapEntry;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 
 final class MapModificationStrategy extends AbstractNodeContainerModificationStrategy {
-    private static final MapEntry<OrderedMapNode> ORDERED_SUPPORT = new MapEntry<>(OrderedMapNode.class,
-            ChildTrackingPolicy.ORDERED, ImmutableOrderedMapNodeBuilder::create,
-            ImmutableOrderedMapNodeBuilder::create);
-    private static final MapEntry<MapNode> UNORDERED_SUPPORT = new MapEntry<>(MapNode.class,
-            ChildTrackingPolicy.UNORDERED, ImmutableMapNodeBuilder::create, ImmutableMapNodeBuilder::create);
+    private static final NormalizedNodeContainerSupport<NodeIdentifier, OrderedMapNode> ORDERED_SUPPORT =
+            new NormalizedNodeContainerSupport<>(OrderedMapNode.class, ChildTrackingPolicy.ORDERED,
+                    ImmutableOrderedMapNodeBuilder::create, ImmutableOrderedMapNodeBuilder::create);
+    private static final NormalizedNodeContainerSupport<NodeIdentifier, MapNode> UNORDERED_SUPPORT =
+            new NormalizedNodeContainerSupport<>(MapNode.class, ImmutableMapNodeBuilder::create,
+                    ImmutableMapNodeBuilder::create);
 
     private final Optional<ModificationApplyOperation> entryStrategy;
     private final MapNode emptyNode;
 
-    private MapModificationStrategy(final MapEntry<?> support, final ListSchemaNode schema,
+    private MapModificationStrategy(final NormalizedNodeContainerSupport<?, ?> support, final ListSchemaNode schema,
         final DataTreeConfiguration treeConfig, final MapNode emptyNode) {
         super(support, treeConfig);
         this.emptyNode = requireNonNull(emptyNode);
@@ -43,7 +44,7 @@ final class MapModificationStrategy extends AbstractNodeContainerModificationStr
     }
 
     static MapModificationStrategy of(final ListSchemaNode schema, final DataTreeConfiguration treeConfig) {
-        final MapEntry<?> support;
+        final NormalizedNodeContainerSupport<?, ?> support;
         final MapNode emptyNode;
         if (schema.isUserOrdered()) {
             support = ORDERED_SUPPORT;
@@ -55,19 +56,9 @@ final class MapModificationStrategy extends AbstractNodeContainerModificationStr
         return new MapModificationStrategy(support, schema, treeConfig, emptyNode);
     }
 
-    // FIXME: this is a hack, originally introduced in
-    //        Change-Id: I9dc02a1917f38e8a0d62279843974b9869c48693. DataTreeRoot needs to be fixed up to properly
-    //        handle the lookup of through maps.
     @Override
     public Optional<ModificationApplyOperation> getChild(final YangInstanceIdentifier.PathArgument identifier) {
-        if (identifier instanceof NodeIdentifierWithPredicates) {
-            return entryStrategy;
-        }
-        // In case we already are in a MapEntry node(for example DataTree rooted at MapEntry)
-        // try to retrieve the child that the identifier should be pointing to from our entryStrategy
-        // if we have one. If the entryStrategy cannot find this child we just return the absent
-        // we get from it.
-        return entryStrategy.get().getChild(identifier);
+        return identifier instanceof NodeIdentifierWithPredicates ? entryStrategy : Optional.empty();
     }
 
     @Override
index fe82ab8bc5e410702bfa74587c581c9e5cd41087..e1e1b88885dc75955746fffd59136a4fc94938a0 100644 (file)
@@ -13,81 +13,11 @@ import static java.util.Objects.requireNonNull;
 import com.google.common.base.MoreObjects;
 import java.util.function.Function;
 import java.util.function.Supplier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
-
-abstract class NormalizedNodeContainerSupport<K extends PathArgument, T extends NormalizedNode<K, ?>> {
-    static final class Single<K extends PathArgument, T extends NormalizedNode<K, ?>>
-            extends NormalizedNodeContainerSupport<K, T> {
-        Single(final Class<T> requiredClass,
-                final Function<T, NormalizedNodeContainerBuilder<K, ?, ?, T>> copyBuilder,
-                final Supplier<NormalizedNodeContainerBuilder<K, ?, ?, T>> emptyBuilder) {
-            this(requiredClass, ChildTrackingPolicy.UNORDERED, copyBuilder, emptyBuilder);
-        }
-
-        Single(final Class<T> requiredClass, final ChildTrackingPolicy childPolicy,
-                final Function<T, NormalizedNodeContainerBuilder<K, ?, ?, T>> copyBuilder,
-                final Supplier<NormalizedNodeContainerBuilder<K, ?, ?, T>> emptyBuilder) {
-            super(requiredClass, childPolicy, copyBuilder, emptyBuilder);
-        }
-
-        @Override
-        NormalizedNodeContainerBuilder<?, ?, ?, T> createBuilder(final NormalizedNode<?, ?> original) {
-            return copyBuilder.apply(cast(original));
-        }
-
-        @Override
-        NormalizedNode<?, ?> createEmptyValue(final NormalizedNode<?, ?> original) {
-            return emptyBuilder.get().withNodeIdentifier(cast(original).getIdentifier()).build();
-        }
-
-        private T cast(final NormalizedNode<?, ?> original) {
-            checkArgument(requiredClass.isInstance(original), "Require %s, got %s", requiredClass, original);
-            return requiredClass.cast(original);
-        }
-    }
-
-    // FIXME: MapEntry a refactor of a hack, originally introduced in
-    //        Change-Id: I9dc02a1917f38e8a0d62279843974b9869c48693. DataTreeRoot needs to be fixed up to properly
-    //        handle the lookup of through maps.
-    static final class MapEntry<T extends NormalizedNode<NodeIdentifier, ?>>
-            extends NormalizedNodeContainerSupport<NodeIdentifier, T> {
-        MapEntry(final Class<T> requiredClass, final ChildTrackingPolicy childPolicy,
-                final Function<T, NormalizedNodeContainerBuilder<NodeIdentifier, ?, ?, T>> copyBuilder,
-                final Supplier<NormalizedNodeContainerBuilder<NodeIdentifier, ?, ?, T>> emptyBuilder) {
-            super(requiredClass, childPolicy, copyBuilder, emptyBuilder);
-        }
-
-        @Override
-        NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final NormalizedNode<?, ?> original) {
-            if (requiredClass.isInstance(original)) {
-                return copyBuilder.apply(requiredClass.cast(original));
-            }
-            if (original instanceof MapEntryNode) {
-                return ImmutableMapEntryNodeBuilder.create((MapEntryNode) original);
-            }
-            throw new IllegalArgumentException("Expected either MapEntryNode or " + requiredClass + ", offending node: "
-                    + original);
-        }
-
-        @Override
-        NormalizedNode<?, ?> createEmptyValue(final NormalizedNode<?, ?> original) {
-            if (requiredClass.isInstance(original)) {
-                return emptyBuilder.get().withNodeIdentifier(requiredClass.cast(original).getIdentifier()).build();
-            }
-            if (original instanceof MapEntryNode) {
-                return ImmutableMapEntryNodeBuilder.create()
-                        .withNodeIdentifier(((MapEntryNode) original).getIdentifier()).build();
-            }
-            throw new IllegalArgumentException("Expected either MapEntryNode or " + requiredClass + ", offending node: "
-                    + original);
-        }
-    }
 
+final class NormalizedNodeContainerSupport<K extends PathArgument, T extends NormalizedNode<K, ?>> {
     final Function<T, NormalizedNodeContainerBuilder<K, ?, ?, T>> copyBuilder;
     final Supplier<NormalizedNodeContainerBuilder<K, ?, ?, T>> emptyBuilder;
     final ChildTrackingPolicy childPolicy;
@@ -102,13 +32,27 @@ abstract class NormalizedNodeContainerSupport<K extends PathArgument, T extends
         this.emptyBuilder = requireNonNull(emptyBuilder);
     }
 
-    @SuppressWarnings("rawtypes")
-    abstract NormalizedNodeContainerBuilder createBuilder(NormalizedNode<?, ?> original);
+    NormalizedNodeContainerSupport(final Class<T> requiredClass,
+            final Function<T, NormalizedNodeContainerBuilder<K, ?, ?, T>> copyBuilder,
+            final Supplier<NormalizedNodeContainerBuilder<K, ?, ?, T>> emptyBuilder) {
+        this(requiredClass, ChildTrackingPolicy.UNORDERED, copyBuilder, emptyBuilder);
+    }
 
-    abstract NormalizedNode<?, ?> createEmptyValue(NormalizedNode<?, ?> original);
+    NormalizedNodeContainerBuilder<?, ?, ?, T> createBuilder(final NormalizedNode<?, ?> original) {
+        return copyBuilder.apply(cast(original));
+    }
+
+    NormalizedNode<?, ?> createEmptyValue(final NormalizedNode<?, ?> original) {
+        return emptyBuilder.get().withNodeIdentifier(cast(original).getIdentifier()).build();
+    }
+
+    private T cast(final NormalizedNode<?, ?> original) {
+        checkArgument(requiredClass.isInstance(original), "Require %s, got %s", requiredClass, original);
+        return requiredClass.cast(original);
+    }
 
     @Override
-    public final String toString() {
+    public String toString() {
         return MoreObjects.toStringHelper(this).add("requiredClass", requiredClass).toString();
     }
 }
index 3bc3b5c0ec02b7c24fd8ac2926054a6eeff47978..eae59539a7ee49e66a098b6bd88f856f0ab4cd07 100644 (file)
@@ -23,13 +23,12 @@ import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.Version;
 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableUnkeyedListEntryNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.tree.NormalizedNodeContainerSupport.Single;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 
 final class UnkeyedListModificationStrategy extends SchemaAwareApplyOperation {
-    private static final Single<NodeIdentifier, UnkeyedListEntryNode> ITEM_SUPPORT =
-            new Single<>(UnkeyedListEntryNode.class, ImmutableUnkeyedListEntryNodeBuilder::create,
-                    ImmutableUnkeyedListEntryNodeBuilder::create);
+    private static final NormalizedNodeContainerSupport<NodeIdentifier, UnkeyedListEntryNode> ITEM_SUPPORT =
+            new NormalizedNodeContainerSupport<>(UnkeyedListEntryNode.class,
+                    ImmutableUnkeyedListEntryNodeBuilder::create, ImmutableUnkeyedListEntryNodeBuilder::create);
 
     private final Optional<ModificationApplyOperation> entryStrategy;
     private final UnkeyedListNode emptyNode;
diff --git a/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/MapEntryRootTest.java b/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/MapEntryRootTest.java
new file mode 100644 (file)
index 0000000..fee1b19
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2019 Pantheon Technologies, 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.yangtools.yang.data.impl.schema.tree;
+
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeConfiguration;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.TreeType;
+
+public class MapEntryRootTest extends AbstractTestModelTest {
+
+    @Test
+    public void testMapEntryRoot() {
+        final DataTreeConfiguration treeConfig = DataTreeConfiguration.builder(TreeType.OPERATIONAL).setRootPath(
+            TestModel.TEST_PATH.node(TestModel.OUTER_LIST_QNAME).node(
+                new NodeIdentifierWithPredicates(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, (short) 12))).build();
+        final DataTree dataTree = new InMemoryDataTreeFactory().create(treeConfig, SCHEMA_CONTEXT);
+        assertTrue(dataTree instanceof InMemoryDataTree);
+
+        final InMemoryDataTree imdt = (InMemoryDataTree) dataTree;
+        final InMemoryDataTreeModification mod = imdt.takeSnapshot().newModification();
+        final ModificationApplyOperation strategy = mod.getStrategy();
+        assertThat(strategy, instanceOf(ListEntryModificationStrategy.class));
+    }
+}