Fixup rfc8528-data-api module-info
[yangtools.git] / yang / yang-data-impl / src / main / java / org / opendaylight / yangtools / yang / data / impl / schema / InstanceIdToCompositeNodes.java
index 69618f5128b6a05f63bb68b1db2becfab28d4fb0..1b85302faf4036ba15ea5bf5b3deebdaa5bee6d2 100644 (file)
@@ -8,98 +8,93 @@
 package org.opendaylight.yangtools.yang.data.impl.schema;
 
 import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
+import static com.google.common.base.Verify.verify;
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
 import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
 import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
 import java.util.Map;
-import java.util.Set;
+import java.util.Map.Entry;
+import java.util.Optional;
 import java.util.concurrent.ConcurrentHashMap;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.util.ImmutableOffsetMap;
 import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.ModifyAction;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
+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.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.AttributesBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
+import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode;
+import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.ListNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
-import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
-import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.yangtools.yang.data.util.DataSchemaContextNode;
+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.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ContainerLike;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 import org.opendaylight.yangtools.yang.model.util.EffectiveAugmentationSchema;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
-* Base strategy for converting an instance identifier into a normalized node structure for container-like types.
-*/
-abstract class InstanceIdToCompositeNodes<T extends YangInstanceIdentifier.PathArgument> extends
-        InstanceIdToNodes<T> {
+ * Base strategy for converting an instance identifier into a normalized node structure for container-like types.
+ */
+abstract class InstanceIdToCompositeNodes<T extends PathArgument> extends InstanceIdToNodes<T> {
+    private static final Logger LOG = LoggerFactory.getLogger(InstanceIdToCompositeNodes.class);
 
-    protected InstanceIdToCompositeNodes(final T identifier) {
+    InstanceIdToCompositeNodes(final T identifier) {
         super(identifier);
     }
 
-    private static YangInstanceIdentifier.AugmentationIdentifier augmentationIdentifierFrom(final AugmentationSchema augmentation) {
-        final ImmutableSet.Builder<QName> potentialChildren = ImmutableSet.builder();
-        for (final DataSchemaNode child : augmentation.getChildNodes()) {
-            potentialChildren.add(child.getQName());
-        }
-        return new YangInstanceIdentifier.AugmentationIdentifier(potentialChildren.build());
-    }
-
-    private static DataNodeContainer augmentationProxy(final AugmentationSchema augmentation, final DataNodeContainer schema) {
-        final Set<DataSchemaNode> children = new HashSet<>();
-        for (final DataSchemaNode augNode : augmentation.getChildNodes()) {
-            children.add(schema.getDataChildByName(augNode.getQName()));
-        }
-        return new EffectiveAugmentationSchema(augmentation, children);
-    }
-
     @Override
     @SuppressWarnings("unchecked")
-    public final NormalizedNode<?, ?> create(final YangInstanceIdentifier instanceId, final Optional<NormalizedNode<?, ?>> lastChild, final Optional<Map.Entry<QName,ModifyAction>> operation) {
-        checkNotNull(instanceId);
-        final Iterator<YangInstanceIdentifier.PathArgument> iterator = instanceId.getPathArguments().iterator();
-        final YangInstanceIdentifier.PathArgument legacyData = iterator.next();
-
-        if (!isMixin(this) && getIdentifier().getNodeType() != null) {
-            checkArgument(getIdentifier().getNodeType().equals(legacyData.getNodeType()),
-                    "Node QName must be %s was %s", getIdentifier().getNodeType(), legacyData.getNodeType());
-        }
-        final NormalizedNodeContainerBuilder builder = createBuilder(legacyData);
-
-        if (iterator.hasNext()) {
-            final YangInstanceIdentifier.PathArgument childPath = iterator.next();
-            final InstanceIdToNodes childOp = getChildOperation(childPath);
-
-            final YangInstanceIdentifier childId = YangInstanceIdentifier.create(Iterables.skip(instanceId.getPathArguments(), 1));
-            builder.addChild(childOp.create(childId, lastChild, operation));
-        } else {
-            if(lastChild.isPresent()) {
-                builder.withValue(Lists.newArrayList((Collection<?>) lastChild.get().getValue()));
-            }
-            if(operation.isPresent()) {
-                Preconditions.checkArgument(builder instanceof AttributesBuilder<?>);
-                addModifyOpIfPresent(operation, ((AttributesBuilder<?>) builder));
+    final NormalizedNode<?, ?> create(final PathArgument first, final Iterator<PathArgument> others,
+            final Optional<NormalizedNode<?, ?>> lastChild) {
+        if (!isMixin()) {
+            final QName type = getIdentifier().getNodeType();
+            if (type != null) {
+                final QName firstType = first.getNodeType();
+                checkArgument(type.equals(firstType), "Node QName must be %s was %s", type, firstType);
             }
         }
 
+        @SuppressWarnings("rawtypes")
+        final NormalizedNodeContainerBuilder builder = createBuilder(first);
+
+        if (others.hasNext()) {
+            final PathArgument childPath = others.next();
+            final InstanceIdToNodes<?> childOp = getChildOperation(childPath);
+            builder.addChild(childOp.create(childPath, others, lastChild));
+        } else if (lastChild.isPresent()) {
+            builder.withValue(ImmutableList.copyOf((Collection<?>) lastChild.get().getValue()));
+        }
+
         return builder.build();
     }
 
-    private InstanceIdToNodes getChildOperation(final YangInstanceIdentifier.PathArgument childPath) {
-        final InstanceIdToNodes childOp;
+    @SuppressWarnings("checkstyle:illegalCatch")
+    private InstanceIdToNodes<?> getChildOperation(final PathArgument childPath) {
+        final InstanceIdToNodes<?> childOp;
         try {
             childOp = getChild(childPath);
         } catch (final RuntimeException e) {
@@ -109,33 +104,35 @@ abstract class InstanceIdToCompositeNodes<T extends YangInstanceIdentifier.PathA
         return childOp;
     }
 
-    protected abstract NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode);
+    abstract NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(PathArgument compositeNode);
 
-    static abstract class DataContainerNormalizationOperation<T extends YangInstanceIdentifier.PathArgument> extends
-            InstanceIdToCompositeNodes<T> {
+    abstract static class DataContainerNormalizationOperation<T extends PathArgument, S extends DataNodeContainer>
+            extends InstanceIdToCompositeNodes<T> {
 
-        private final DataNodeContainer schema;
-        private final Map<YangInstanceIdentifier.PathArgument, InstanceIdToNodes<?>> byArg;
+        private final Map<PathArgument, InstanceIdToNodes<?>> byArg = new ConcurrentHashMap<>();
+        private final @NonNull S schema;
 
-        protected DataContainerNormalizationOperation(final T identifier, final DataNodeContainer schema) {
+        DataContainerNormalizationOperation(final T identifier, final S schema) {
             super(identifier);
-            this.schema = schema;
-            this.byArg = new ConcurrentHashMap<>();
+            this.schema = requireNonNull(schema);
         }
 
         @Override
-        public InstanceIdToNodes<?> getChild(final YangInstanceIdentifier.PathArgument child) {
-            InstanceIdToNodes<?> potential = byArg.get(child);
-            if (potential != null) {
-                return potential;
+        final InstanceIdToNodes<?> getChild(final PathArgument child) {
+            final InstanceIdToNodes<?> existing = byArg.get(child);
+            if (existing != null) {
+                return existing;
             }
-            potential = fromLocalSchema(child);
-            return register(potential);
+            return register(fromLocalSchema(child));
+        }
+
+        final @NonNull S schema() {
+            return schema;
         }
 
-        private InstanceIdToNodes<?> fromLocalSchema(final YangInstanceIdentifier.PathArgument child) {
-            if (child instanceof YangInstanceIdentifier.AugmentationIdentifier) {
-                return fromSchemaAndQNameChecked(schema, ((YangInstanceIdentifier.AugmentationIdentifier) child).getPossibleChildNames()
+        private InstanceIdToNodes<?> fromLocalSchema(final PathArgument child) {
+            if (child instanceof AugmentationIdentifier) {
+                return fromSchemaAndQNameChecked(schema, ((AugmentationIdentifier) child).getPossibleChildNames()
                         .iterator().next());
             }
             return fromSchemaAndQNameChecked(schema, child.getNodeType());
@@ -149,147 +146,199 @@ abstract class InstanceIdToCompositeNodes<T extends YangInstanceIdentifier.PathA
         }
     }
 
-    static final class ListItemNormalization extends
-            DataContainerNormalizationOperation<YangInstanceIdentifier.NodeIdentifierWithPredicates> {
+    static final class MapEntryNormalization
+            extends DataContainerNormalizationOperation<NodeIdentifierWithPredicates, ListSchemaNode> {
+        MapEntryNormalization(final ListSchemaNode schema) {
+            super(NodeIdentifierWithPredicates.of(schema.getQName()), schema);
+        }
 
-        protected ListItemNormalization(final YangInstanceIdentifier.NodeIdentifierWithPredicates identifier, final ListSchemaNode schema) {
-            super(identifier, schema);
+        @Override
+        boolean isMixin() {
+            return false;
         }
 
         @Override
-        protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument currentArg) {
-            final DataContainerNodeAttrBuilder<YangInstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> builder = Builders
-                    .mapEntryBuilder().withNodeIdentifier((YangInstanceIdentifier.NodeIdentifierWithPredicates) currentArg);
-            for (final Map.Entry<QName, Object> keyValue : ((YangInstanceIdentifier.NodeIdentifierWithPredicates) currentArg).getKeyValues().entrySet()) {
+        DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> createBuilder(
+                final PathArgument currentArg) {
+            final NodeIdentifierWithPredicates arg = (NodeIdentifierWithPredicates) currentArg;
+            return createBuilder(arg.size() < 2 ? arg : reorderPredicates(schema().getKeyDefinition(), arg));
+        }
+
+        private static DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> createBuilder(
+                final NodeIdentifierWithPredicates arg) {
+            final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> builder = Builders
+                    .mapEntryBuilder().withNodeIdentifier(arg);
+            for (final Entry<QName, Object> keyValue : arg.entrySet()) {
                 builder.addChild(Builders.leafBuilder()
-                        //
-                        .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(keyValue.getKey())).withValue(keyValue.getValue())
+                        .withNodeIdentifier(NodeIdentifier.create(keyValue.getKey())).withValue(keyValue.getValue())
                         .build());
             }
             return builder;
         }
 
-    }
+        private static NodeIdentifierWithPredicates reorderPredicates(final List<QName> keys,
+                final NodeIdentifierWithPredicates arg) {
+            if (Iterables.elementsEqual(keys, arg.keySet())) {
+                // Iteration order matches key order, reuse the identifier
+                return arg;
+            }
 
-    static final class UnkeyedListItemNormalization extends DataContainerNormalizationOperation<YangInstanceIdentifier.NodeIdentifier> {
+            // We care about iteration order here!
+            final LinkedHashMap<QName, Object> map = Maps.newLinkedHashMapWithExpectedSize(arg.size());
+            for (QName qname : keys) {
+                final Object value = arg.getValue(qname);
+                if (value != null) {
+                    map.put(qname, value);
+                }
+            }
+            if (map.size() < arg.size()) {
+                // Okay, this should not happen, but let's handle that anyway
+                LOG.debug("Extra predicates in {} while expecting {}", arg, keys);
+                for (Entry<QName, Object> entry : arg.entrySet()) {
+                    map.putIfAbsent(entry.getKey(), entry.getValue());
+                }
+            }
+
+            // This copy retains iteration order and since we have more than one argument, it should always be
+            // and ImmutableOffsetMap -- which is guaranteed to be taken as-is
+            final Map<QName, Object> copy = ImmutableOffsetMap.orderedCopyOf(map);
+            verify(copy instanceof ImmutableOffsetMap);
+            return NodeIdentifierWithPredicates.of(arg.getNodeType(), (ImmutableOffsetMap<QName, Object>) copy);
+        }
+    }
 
-        protected UnkeyedListItemNormalization(final ListSchemaNode schema) {
-            super(new YangInstanceIdentifier.NodeIdentifier(schema.getQName()), schema);
+    static final class UnkeyedListItemNormalization
+            extends DataContainerNormalizationOperation<NodeIdentifier, ListSchemaNode> {
+        UnkeyedListItemNormalization(final ListSchemaNode schema) {
+            super(NodeIdentifier.create(schema.getQName()), schema);
         }
 
         @Override
-        protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode) {
+        DataContainerNodeBuilder<NodeIdentifier, UnkeyedListEntryNode> createBuilder(
+                final PathArgument compositeNode) {
             return Builders.unkeyedListEntryBuilder().withNodeIdentifier(getIdentifier());
         }
 
+        @Override
+        boolean isMixin() {
+            return false;
+        }
     }
 
-    static final class ContainerTransformation extends DataContainerNormalizationOperation<YangInstanceIdentifier.NodeIdentifier> {
-
-        protected ContainerTransformation(final ContainerSchemaNode schema) {
-            super(new YangInstanceIdentifier.NodeIdentifier(schema.getQName()), schema);
+    static final class ContainerTransformation
+            extends DataContainerNormalizationOperation<NodeIdentifier, ContainerLike> {
+        ContainerTransformation(final ContainerLike schema) {
+            super(NodeIdentifier.create(schema.getQName()), schema);
         }
 
         @Override
-        protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode) {
+        DataContainerNodeBuilder<NodeIdentifier, ContainerNode> createBuilder(final PathArgument compositeNode) {
             return Builders.containerBuilder().withNodeIdentifier(getIdentifier());
         }
+
+        @Override
+        boolean isMixin() {
+            return false;
+        }
     }
 
     static final class OrderedLeafListMixinNormalization extends UnorderedLeafListMixinNormalization {
-
-
-        public OrderedLeafListMixinNormalization(final LeafListSchemaNode potential) {
+        OrderedLeafListMixinNormalization(final LeafListSchemaNode potential) {
             super(potential);
         }
 
         @Override
-        protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode) {
+        ListNodeBuilder<?, ?> createBuilder(final PathArgument compositeNode) {
             return Builders.orderedLeafSetBuilder().withNodeIdentifier(getIdentifier());
         }
     }
 
-    static class UnorderedLeafListMixinNormalization extends InstanceIdToCompositeNodes<YangInstanceIdentifier.NodeIdentifier> implements MixinNormalizationOp {
-
+    static class UnorderedLeafListMixinNormalization extends InstanceIdToCompositeNodes<NodeIdentifier> {
         private final InstanceIdToNodes<?> innerOp;
 
-        public UnorderedLeafListMixinNormalization(final LeafListSchemaNode potential) {
-            super(new YangInstanceIdentifier.NodeIdentifier(potential.getQName()));
+        UnorderedLeafListMixinNormalization(final LeafListSchemaNode potential) {
+            super(NodeIdentifier.create(potential.getQName()));
             innerOp = new InstanceIdToSimpleNodes.LeafListEntryNormalization(potential);
         }
 
         @Override
-        protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode) {
+        ListNodeBuilder<?, ?> createBuilder(final PathArgument compositeNode) {
             return Builders.leafSetBuilder().withNodeIdentifier(getIdentifier());
         }
 
         @Override
-        public InstanceIdToNodes<?> getChild(final YangInstanceIdentifier.PathArgument child) {
-            if (child instanceof YangInstanceIdentifier.NodeWithValue) {
-                return innerOp;
-            }
-            return null;
+        final InstanceIdToNodes<?> getChild(final PathArgument child) {
+            return child instanceof NodeWithValue ? innerOp : null;
         }
-    }
 
-    static final class AugmentationNormalization extends DataContainerNormalizationOperation<YangInstanceIdentifier.AugmentationIdentifier> implements MixinNormalizationOp {
+        @Override
+        final boolean isMixin() {
+            return true;
+        }
+    }
 
-        public AugmentationNormalization(final AugmentationSchema augmentation, final DataNodeContainer schema) {
-            super(augmentationIdentifierFrom(augmentation), augmentationProxy(augmentation, schema));
+    static final class AugmentationNormalization
+            extends DataContainerNormalizationOperation<AugmentationIdentifier, AugmentationSchemaNode> {
+        AugmentationNormalization(final AugmentationSchemaNode augmentation, final DataNodeContainer schema) {
+            super(DataSchemaContextNode.augmentationIdentifierFrom(augmentation),
+                    EffectiveAugmentationSchema.create(augmentation, schema));
         }
 
         @Override
-        protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode) {
+        DataContainerNodeBuilder<AugmentationIdentifier, AugmentationNode> createBuilder(
+                final PathArgument compositeNode) {
             return Builders.augmentationBuilder().withNodeIdentifier(getIdentifier());
         }
-    }
 
-    static class UnorderedMapMixinNormalization extends InstanceIdToCompositeNodes<YangInstanceIdentifier.NodeIdentifier> implements MixinNormalizationOp {
+        @Override
+        boolean isMixin() {
+            return true;
+        }
+    }
 
-        private final ListItemNormalization innerNode;
+    static class UnorderedMapMixinNormalization extends InstanceIdToCompositeNodes<NodeIdentifier> {
+        private final MapEntryNormalization innerNode;
 
-        public UnorderedMapMixinNormalization(final ListSchemaNode list) {
-            super(new YangInstanceIdentifier.NodeIdentifier(list.getQName()));
-            this.innerNode = new ListItemNormalization(new YangInstanceIdentifier.NodeIdentifierWithPredicates(list.getQName(),
-                    Collections.<QName, Object>emptyMap()), list);
+        UnorderedMapMixinNormalization(final ListSchemaNode list) {
+            super(NodeIdentifier.create(list.getQName()));
+            this.innerNode = new MapEntryNormalization(list);
         }
 
         @Override
-        protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode) {
+        CollectionNodeBuilder<MapEntryNode, ? extends MapNode> createBuilder(final PathArgument compositeNode) {
             return Builders.mapBuilder().withNodeIdentifier(getIdentifier());
         }
 
         @Override
-        public InstanceIdToNodes<?> getChild(final YangInstanceIdentifier.PathArgument child) {
-            if (child.getNodeType().equals(getIdentifier().getNodeType())) {
-                return innerNode;
-            }
-            return null;
+        final InstanceIdToNodes<?> getChild(final PathArgument child) {
+            return child.getNodeType().equals(getIdentifier().getNodeType()) ? innerNode : null;
+        }
+
+        @Override
+        final boolean isMixin() {
+            return true;
         }
     }
 
     static final class OrderedMapMixinNormalization extends UnorderedMapMixinNormalization {
-
-        public OrderedMapMixinNormalization(final ListSchemaNode list) {
+        OrderedMapMixinNormalization(final ListSchemaNode list) {
             super(list);
         }
 
         @Override
-        protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode) {
+        CollectionNodeBuilder<MapEntryNode, OrderedMapNode> createBuilder(final PathArgument compositeNode) {
             return Builders.orderedMapBuilder().withNodeIdentifier(getIdentifier());
         }
-
     }
 
-    static class ChoiceNodeNormalization extends InstanceIdToCompositeNodes<YangInstanceIdentifier.NodeIdentifier> implements MixinNormalizationOp {
-
-        private final ImmutableMap<YangInstanceIdentifier.PathArgument, InstanceIdToNodes<?>> byArg;
+    static final class ChoiceNodeNormalization extends InstanceIdToCompositeNodes<NodeIdentifier> {
+        private final ImmutableMap<PathArgument, InstanceIdToNodes<?>> byArg;
 
-        protected ChoiceNodeNormalization(final ChoiceSchemaNode schema) {
-            super(new YangInstanceIdentifier.NodeIdentifier(schema.getQName()));
-            final ImmutableMap.Builder<YangInstanceIdentifier.PathArgument, InstanceIdToNodes<?>> byArgBuilder = ImmutableMap.builder();
+        ChoiceNodeNormalization(final ChoiceSchemaNode schema) {
+            super(NodeIdentifier.create(schema.getQName()));
+            final ImmutableMap.Builder<PathArgument, InstanceIdToNodes<?>> byArgBuilder = ImmutableMap.builder();
 
-            for (final ChoiceCaseNode caze : schema.getCases()) {
+            for (final CaseSchemaNode caze : schema.getCases()) {
                 for (final DataSchemaNode cazeChild : caze.getChildNodes()) {
                     final InstanceIdToNodes<?> childOp = fromDataSchemaNode(cazeChild);
                     byArgBuilder.put(childOp.getIdentifier(), childOp);
@@ -299,13 +348,18 @@ abstract class InstanceIdToCompositeNodes<T extends YangInstanceIdentifier.PathA
         }
 
         @Override
-        public InstanceIdToNodes<?> getChild(final YangInstanceIdentifier.PathArgument child) {
+        InstanceIdToNodes<?> getChild(final PathArgument child) {
             return byArg.get(child);
         }
 
         @Override
-        protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode) {
+        DataContainerNodeBuilder<NodeIdentifier, ChoiceNode> createBuilder(final PathArgument compositeNode) {
             return Builders.choiceBuilder().withNodeIdentifier(getIdentifier());
         }
+
+        @Override
+        boolean isMixin() {
+            return true;
+        }
     }
 }