Bug 4295: Fixed incorrectly introduced nodes when MERGE was followed by DELETE
[yangtools.git] / yang / yang-data-impl / src / main / java / org / opendaylight / yangtools / yang / data / impl / schema / InstanceIdToCompositeNodes.java
index 28e8d892f0dba1a9cdf9b0670d5964d4d4a30856..aa777d2fecaf395758ceae54a03e9215a2003671 100644 (file)
@@ -9,7 +9,6 @@ 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 com.google.common.collect.ImmutableMap;
@@ -26,10 +25,24 @@ import java.util.concurrent.ConcurrentHashMap;
 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.api.schema.OrderedMapNode;
+import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.AttributesBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
+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;
@@ -44,19 +57,18 @@ import org.opendaylight.yangtools.yang.model.util.EffectiveAugmentationSchema;
 /**
 * 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> {
+abstract class InstanceIdToCompositeNodes<T extends PathArgument> extends InstanceIdToNodes<T> {
 
     protected InstanceIdToCompositeNodes(final T identifier) {
         super(identifier);
     }
 
-    private static YangInstanceIdentifier.AugmentationIdentifier augmentationIdentifierFrom(final AugmentationSchema augmentation) {
+    private static 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());
+        return new AugmentationIdentifier(potentialChildren.build());
     }
 
     private static DataNodeContainer augmentationProxy(final AugmentationSchema augmentation, final DataNodeContainer schema) {
@@ -71,26 +83,27 @@ abstract class InstanceIdToCompositeNodes<T extends YangInstanceIdentifier.PathA
     @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();
+        final Iterator<PathArgument> iterator = instanceId.getPathArguments().iterator();
+        final PathArgument legacyData = iterator.next();
 
-        if (!isMixin(this) && getIdentifier().getNodeType() != null) {
+        if (!isMixin() && getIdentifier().getNodeType() != null) {
             checkArgument(getIdentifier().getNodeType().equals(legacyData.getNodeType()),
                     "Node QName must be %s was %s", getIdentifier().getNodeType(), legacyData.getNodeType());
         }
+        @SuppressWarnings("rawtypes")
         final NormalizedNodeContainerBuilder builder = createBuilder(legacyData);
 
         if (iterator.hasNext()) {
-            final YangInstanceIdentifier.PathArgument childPath = iterator.next();
-            final InstanceIdToNodes childOp = getChildOperation(childPath);
+            final 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()) {
+            if (lastChild.isPresent()) {
                 builder.withValue(Lists.newArrayList((Collection<?>) lastChild.get().getValue()));
             }
-            if(operation.isPresent()) {
+            if (operation.isPresent()) {
                 Preconditions.checkArgument(builder instanceof AttributesBuilder<?>);
                 addModifyOpIfPresent(operation, ((AttributesBuilder<?>) builder));
             }
@@ -99,8 +112,8 @@ abstract class InstanceIdToCompositeNodes<T extends YangInstanceIdentifier.PathA
         return builder.build();
     }
 
-    private InstanceIdToNodes getChildOperation(final YangInstanceIdentifier.PathArgument childPath) {
-        final InstanceIdToNodes childOp;
+    private InstanceIdToNodes<?> getChildOperation(final PathArgument childPath) {
+        final InstanceIdToNodes<?> childOp;
         try {
             childOp = getChild(childPath);
         } catch (final RuntimeException e) {
@@ -110,14 +123,13 @@ abstract class InstanceIdToCompositeNodes<T extends YangInstanceIdentifier.PathA
         return childOp;
     }
 
-    @SuppressWarnings("rawtypes")
-    protected abstract NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode);
+    protected abstract NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final PathArgument compositeNode);
 
-    static abstract class DataContainerNormalizationOperation<T extends YangInstanceIdentifier.PathArgument> extends
+    static abstract class DataContainerNormalizationOperation<T extends PathArgument> extends
             InstanceIdToCompositeNodes<T> {
 
         private final DataNodeContainer schema;
-        private final Map<YangInstanceIdentifier.PathArgument, InstanceIdToNodes<?>> byArg;
+        private final Map<PathArgument, InstanceIdToNodes<?>> byArg;
 
         protected DataContainerNormalizationOperation(final T identifier, final DataNodeContainer schema) {
             super(identifier);
@@ -126,7 +138,7 @@ abstract class InstanceIdToCompositeNodes<T extends YangInstanceIdentifier.PathA
         }
 
         @Override
-        public InstanceIdToNodes<?> getChild(final YangInstanceIdentifier.PathArgument child) {
+        public InstanceIdToNodes<?> getChild(final PathArgument child) {
             InstanceIdToNodes<?> potential = byArg.get(child);
             if (potential != null) {
                 return potential;
@@ -135,9 +147,9 @@ abstract class InstanceIdToCompositeNodes<T extends YangInstanceIdentifier.PathA
             return register(potential);
         }
 
-        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());
@@ -151,51 +163,60 @@ abstract class InstanceIdToCompositeNodes<T extends YangInstanceIdentifier.PathA
         }
     }
 
-    static final class ListItemNormalization extends
-            DataContainerNormalizationOperation<YangInstanceIdentifier.NodeIdentifierWithPredicates> {
-
-        protected ListItemNormalization(final YangInstanceIdentifier.NodeIdentifierWithPredicates identifier, final ListSchemaNode schema) {
+    static final class ListItemNormalization extends DataContainerNormalizationOperation<NodeIdentifierWithPredicates> {
+        protected ListItemNormalization(final NodeIdentifierWithPredicates identifier, final ListSchemaNode schema) {
             super(identifier, schema);
         }
 
         @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()) {
+        protected DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> createBuilder(final PathArgument currentArg) {
+            final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> builder = Builders
+                    .mapEntryBuilder().withNodeIdentifier((NodeIdentifierWithPredicates) currentArg);
+            for (final Map.Entry<QName, Object> keyValue : ((NodeIdentifierWithPredicates) currentArg).getKeyValues().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;
         }
 
+        @Override
+        boolean isMixin() {
+            return false;
+        }
     }
 
-    static final class UnkeyedListItemNormalization extends DataContainerNormalizationOperation<YangInstanceIdentifier.NodeIdentifier> {
+    static final class UnkeyedListItemNormalization extends DataContainerNormalizationOperation<NodeIdentifier> {
 
         protected UnkeyedListItemNormalization(final ListSchemaNode schema) {
-            super(new YangInstanceIdentifier.NodeIdentifier(schema.getQName()), schema);
+            super(NodeIdentifier.create(schema.getQName()), schema);
         }
 
         @Override
-        protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode) {
+        protected DataContainerNodeAttrBuilder<NodeIdentifier, UnkeyedListEntryNode> createBuilder(final PathArgument compositeNode) {
             return Builders.unkeyedListEntryBuilder().withNodeIdentifier(getIdentifier());
         }
 
+        @Override
+        boolean isMixin() {
+            return false;
+        }
     }
 
-    static final class ContainerTransformation extends DataContainerNormalizationOperation<YangInstanceIdentifier.NodeIdentifier> {
-
+    static final class ContainerTransformation extends DataContainerNormalizationOperation<NodeIdentifier> {
         protected ContainerTransformation(final ContainerSchemaNode schema) {
-            super(new YangInstanceIdentifier.NodeIdentifier(schema.getQName()), schema);
+            super(NodeIdentifier.create(schema.getQName()), schema);
         }
 
         @Override
-        protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode) {
+        protected DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> createBuilder(final PathArgument compositeNode) {
             return Builders.containerBuilder().withNodeIdentifier(getIdentifier());
         }
+
+        @Override
+        boolean isMixin() {
+            return false;
+        }
     }
 
     static final class OrderedLeafListMixinNormalization extends UnorderedLeafListMixinNormalization {
@@ -206,68 +227,83 @@ abstract class InstanceIdToCompositeNodes<T extends YangInstanceIdentifier.PathA
         }
 
         @Override
-        protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode) {
+        protected 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()));
+            super(NodeIdentifier.create(potential.getQName()));
             innerOp = new InstanceIdToSimpleNodes.LeafListEntryNormalization(potential);
         }
 
         @Override
-        protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode) {
+        protected ListNodeBuilder<?, ?> createBuilder(final PathArgument compositeNode) {
             return Builders.leafSetBuilder().withNodeIdentifier(getIdentifier());
         }
 
         @Override
-        public InstanceIdToNodes<?> getChild(final YangInstanceIdentifier.PathArgument child) {
-            if (child instanceof YangInstanceIdentifier.NodeWithValue) {
+        public InstanceIdToNodes<?> getChild(final PathArgument child) {
+            if (child instanceof NodeWithValue) {
                 return innerOp;
             }
             return null;
         }
+
+        @Override
+        boolean isMixin() {
+            return true;
+        }
     }
 
-    static final class AugmentationNormalization extends DataContainerNormalizationOperation<YangInstanceIdentifier.AugmentationIdentifier> implements MixinNormalizationOp {
+    static final class AugmentationNormalization extends DataContainerNormalizationOperation<AugmentationIdentifier> {
 
         public AugmentationNormalization(final AugmentationSchema augmentation, final DataNodeContainer schema) {
             super(augmentationIdentifierFrom(augmentation), augmentationProxy(augmentation, schema));
         }
 
         @Override
-        protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode) {
+        protected DataContainerNodeBuilder<AugmentationIdentifier, AugmentationNode> createBuilder(final PathArgument compositeNode) {
             return Builders.augmentationBuilder().withNodeIdentifier(getIdentifier());
         }
+
+        @Override
+        boolean isMixin() {
+            return true;
+        }
     }
 
-    static class UnorderedMapMixinNormalization extends InstanceIdToCompositeNodes<YangInstanceIdentifier.NodeIdentifier> implements MixinNormalizationOp {
+    static class UnorderedMapMixinNormalization extends InstanceIdToCompositeNodes<NodeIdentifier> {
 
         private final ListItemNormalization innerNode;
 
         public UnorderedMapMixinNormalization(final ListSchemaNode list) {
-            super(new YangInstanceIdentifier.NodeIdentifier(list.getQName()));
-            this.innerNode = new ListItemNormalization(new YangInstanceIdentifier.NodeIdentifierWithPredicates(list.getQName(),
+            super(NodeIdentifier.create(list.getQName()));
+            this.innerNode = new ListItemNormalization(new NodeIdentifierWithPredicates(list.getQName(),
                     Collections.<QName, Object>emptyMap()), list);
         }
 
         @Override
-        protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode) {
+        protected CollectionNodeBuilder<MapEntryNode, ? extends MapNode> createBuilder(final PathArgument compositeNode) {
             return Builders.mapBuilder().withNodeIdentifier(getIdentifier());
         }
 
         @Override
-        public InstanceIdToNodes<?> getChild(final YangInstanceIdentifier.PathArgument child) {
+        public InstanceIdToNodes<?> getChild(final PathArgument child) {
             if (child.getNodeType().equals(getIdentifier().getNodeType())) {
                 return innerNode;
             }
             return null;
         }
+
+        @Override
+        boolean isMixin() {
+            return true;
+        }
     }
 
     static final class OrderedMapMixinNormalization extends UnorderedMapMixinNormalization {
@@ -277,19 +313,19 @@ abstract class InstanceIdToCompositeNodes<T extends YangInstanceIdentifier.PathA
         }
 
         @Override
-        protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode) {
+        protected CollectionNodeBuilder<MapEntryNode, OrderedMapNode> createBuilder(final PathArgument compositeNode) {
             return Builders.orderedMapBuilder().withNodeIdentifier(getIdentifier());
         }
 
     }
 
-    static class ChoiceNodeNormalization extends InstanceIdToCompositeNodes<YangInstanceIdentifier.NodeIdentifier> implements MixinNormalizationOp {
+    static final class ChoiceNodeNormalization extends InstanceIdToCompositeNodes<NodeIdentifier> {
 
-        private final ImmutableMap<YangInstanceIdentifier.PathArgument, InstanceIdToNodes<?>> byArg;
+        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();
+            super(NodeIdentifier.create(schema.getQName()));
+            final ImmutableMap.Builder<PathArgument, InstanceIdToNodes<?>> byArgBuilder = ImmutableMap.builder();
 
             for (final ChoiceCaseNode caze : schema.getCases()) {
                 for (final DataSchemaNode cazeChild : caze.getChildNodes()) {
@@ -301,13 +337,18 @@ abstract class InstanceIdToCompositeNodes<T extends YangInstanceIdentifier.PathA
         }
 
         @Override
-        public InstanceIdToNodes<?> getChild(final YangInstanceIdentifier.PathArgument child) {
+        public InstanceIdToNodes<?> getChild(final PathArgument child) {
             return byArg.get(child);
         }
 
         @Override
-        protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode) {
+        protected DataContainerNodeBuilder<NodeIdentifier, ChoiceNode> createBuilder(final PathArgument compositeNode) {
             return Builders.choiceBuilder().withNodeIdentifier(getIdentifier());
         }
+
+        @Override
+        boolean isMixin() {
+            return true;
+        }
     }
 }