Do not use Iterables when we have a collection
[yangtools.git] / yang / yang-data-impl / src / main / java / org / opendaylight / yangtools / yang / data / impl / schema / tree / NormalizedNodeContainerModificationStrategy.java
index 52aa03eed2be09bd1d526d5f13e56980b0481a12..053d0b02274b5108e7820cfe70c9562e353485e7 100644 (file)
@@ -10,9 +10,10 @@ package org.opendaylight.yangtools.yang.data.impl.schema.tree;
 import static com.google.common.base.Preconditions.checkArgument;
 import com.google.common.base.Optional;
 import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
+import java.util.Collection;
 import java.util.Map;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
@@ -33,7 +34,7 @@ import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMa
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedLeafSetNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedMapNodeBuilder;
 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
-import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
@@ -56,7 +57,7 @@ abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareAp
     @SuppressWarnings("rawtypes")
     @Override
     protected void verifyWrittenStructure(final NormalizedNode<?, ?> writtenValue) {
-        checkArgument(nodeClass.isInstance(writtenValue), "Node should must be of type %s", nodeClass);
+        checkArgument(nodeClass.isInstance(writtenValue), "Node %s is not of type %s", writtenValue, nodeClass);
         checkArgument(writtenValue instanceof NormalizedNodeContainer);
 
         NormalizedNodeContainer container = (NormalizedNodeContainer) writtenValue;
@@ -78,7 +79,7 @@ abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareAp
         final NormalizedNode<?, ?> newValue = modification.getWrittenValue();
         final TreeNode newValueMeta = TreeNodeFactory.createTreeNode(newValue, version);
 
-        if (Iterables.isEmpty(modification.getChildren())) {
+        if (modification.getChildren().isEmpty()) {
             return newValueMeta;
         }
 
@@ -92,6 +93,11 @@ abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareAp
          * As it turns out, once we materialize the written data, we can share the
          * code path with the subtree change. So let's create an unsealed TreeNode
          * and run the common parts on it -- which end with the node being sealed.
+         *
+         * FIXME: this code needs to be moved out from the prepare() path and into
+         *        the read() and seal() paths. Merging of writes needs to be charged
+         *        to the code which originated this, not to the code which is
+         *        attempting to make it visible.
          */
         final MutableTreeNode mutable = newValueMeta.mutable();
         mutable.setSubtreeVersion(version);
@@ -148,10 +154,20 @@ abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareAp
         final MutableTreeNode newMeta = currentMeta.mutable();
         newMeta.setSubtreeVersion(version);
 
+        /*
+         * The user has issued an empty merge operation. In this case we do not perform
+         * a data tree mutation, do not pass GO, and do not collect useless garbage.
+         */
+        final Collection<ModifiedNode> children = modification.getChildren();
+        if (children.isEmpty()) {
+            newMeta.setData(currentMeta.getData());
+            return newMeta.seal();
+        }
+
         @SuppressWarnings("rawtypes")
         NormalizedNodeContainerBuilder dataBuilder = createBuilder(currentMeta.getData());
 
-        return mutateChildren(newMeta, dataBuilder, version, modification.getChildren());
+        return mutateChildren(newMeta, dataBuilder, version, children);
     }
 
     @Override
@@ -191,8 +207,8 @@ abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareAp
 
         private final Map<YangInstanceIdentifier.PathArgument, ModificationApplyOperation> childNodes;
 
-        public ChoiceModificationStrategy(final ChoiceNode schemaNode) {
-            super(org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode.class);
+        public ChoiceModificationStrategy(final ChoiceSchemaNode schemaNode) {
+            super(ChoiceNode.class);
             ImmutableMap.Builder<YangInstanceIdentifier.PathArgument, ModificationApplyOperation> child = ImmutableMap.builder();
 
             for (ChoiceCaseNode caze : schemaNode.getCases()) {
@@ -212,8 +228,8 @@ abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareAp
         @Override
         @SuppressWarnings("rawtypes")
         protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
-            checkArgument(original instanceof org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode);
-            return ImmutableChoiceNodeBuilder.create((org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode) original);
+            checkArgument(original instanceof ChoiceNode);
+            return ImmutableChoiceNodeBuilder.create((ChoiceNode) original);
         }
     }