Split off UnkeyedListModificationStrategy
[yangtools.git] / yang / yang-data-impl / src / main / java / org / opendaylight / yangtools / yang / data / impl / schema / tree / SchemaAwareApplyOperation.java
index d0a0bcd33fe9d7d82df72dedd2700be4fc3f62e7..e721221ee9249db083d16bb9c0fffdd4c1ede5a7 100644 (file)
@@ -9,10 +9,10 @@ package org.opendaylight.yangtools.yang.data.impl.schema.tree;
 
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
+import java.util.List;
 import org.opendaylight.yangtools.yang.common.QName;
 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.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.ConflictingModificationAppliedException;
@@ -20,7 +20,6 @@ import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailed
 import org.opendaylight.yangtools.yang.data.api.schema.tree.IncorrectDataStructureException;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNodeFactory;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.Version;
 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
 import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
@@ -34,8 +33,6 @@ import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.List;
-
 abstract class SchemaAwareApplyOperation implements ModificationApplyOperation {
     private static final Logger LOG = LoggerFactory.getLogger(SchemaAwareApplyOperation.class);
 
@@ -158,7 +155,18 @@ abstract class SchemaAwareApplyOperation implements ModificationApplyOperation {
         }
     }
 
-    protected void checkWriteApplicable(final YangInstanceIdentifier path, final NodeModification modification, final Optional<TreeNode> current) throws DataValidationFailedException {
+    /**
+     * Checks if write operation can be applied to current TreeNode.
+     * The operation checks if original tree node to which the modification is going to be applied exists and if
+     * current node in TreeNode structure exists.
+     *
+     * @param path Path from current node in TreeNode
+     * @param modification modification to apply
+     * @param current current node in TreeNode for modification to apply
+     * @throws DataValidationFailedException
+     */
+    protected void checkWriteApplicable(final YangInstanceIdentifier path, final NodeModification modification,
+        final Optional<TreeNode> current) throws DataValidationFailedException {
         Optional<TreeNode> original = modification.getOriginal();
         if (original.isPresent() && current.isPresent()) {
             checkNotConflicting(path, original.get(), current.get());
@@ -176,25 +184,35 @@ abstract class SchemaAwareApplyOperation implements ModificationApplyOperation {
         }
     }
 
+    boolean isOrdered() {
+        return false;
+    }
+
     @Override
     public final Optional<TreeNode> apply(final ModifiedNode modification,
             final Optional<TreeNode> currentMeta, final Version version) {
 
         switch (modification.getType()) {
         case DELETE:
-            return modification.storeSnapshot(Optional.<TreeNode> absent());
+            return modification.setSnapshot(Optional.<TreeNode> absent());
         case SUBTREE_MODIFIED:
             Preconditions.checkArgument(currentMeta.isPresent(), "Metadata not available for modification",
                     modification);
-            return modification.storeSnapshot(Optional.of(applySubtreeChange(modification, currentMeta.get(),
+            return modification.setSnapshot(Optional.of(applySubtreeChange(modification, currentMeta.get(),
                     version)));
         case MERGE:
-            if(currentMeta.isPresent()) {
-                return modification.storeSnapshot(Optional.of(applyMerge(modification,currentMeta.get(), version)));
+            final TreeNode result;
+
+            // This is a slight optimization: a merge on a non-existing node equals to a write
+            if (currentMeta.isPresent()) {
+                result = applyMerge(modification,currentMeta.get(), version);
+            } else {
+                result = applyWrite(modification, currentMeta, version);
             }
-            // intentional fall-through: if the node does not exist a merge is same as a write
+
+            return modification.setSnapshot(Optional.of(result));
         case WRITE:
-            return modification.storeSnapshot(Optional.of(applyWrite(modification, currentMeta, version)));
+            return modification.setSnapshot(Optional.of(applyWrite(modification, currentMeta, version)));
         case UNMODIFIED:
             return currentMeta;
         default:
@@ -225,55 +243,4 @@ abstract class SchemaAwareApplyOperation implements ModificationApplyOperation {
             final Optional<TreeNode> current) throws DataValidationFailedException;
 
     protected abstract void verifyWrittenStructure(NormalizedNode<?, ?> writtenValue);
-
-    public static class UnkeyedListModificationStrategy extends SchemaAwareApplyOperation {
-
-        private final Optional<ModificationApplyOperation> entryStrategy;
-
-        protected UnkeyedListModificationStrategy(final ListSchemaNode schema) {
-            entryStrategy = Optional.<ModificationApplyOperation> of(new DataNodeContainerModificationStrategy.UnkeyedListItemModificationStrategy(schema));
-        }
-
-        @Override
-        protected TreeNode applyMerge(final ModifiedNode modification, final TreeNode currentMeta,
-                final Version version) {
-            return applyWrite(modification, Optional.of(currentMeta), version);
-        }
-
-        @Override
-        protected TreeNode applySubtreeChange(final ModifiedNode modification,
-                final TreeNode currentMeta, final Version version) {
-            throw new UnsupportedOperationException("UnkeyedList does not support subtree change.");
-        }
-
-        @Override
-        protected TreeNode applyWrite(final ModifiedNode modification,
-                final Optional<TreeNode> currentMeta, final Version version) {
-            /*
-             * FIXME: BUG-1258: This is inefficient: it needlessly creates index nodes for the entire subtree.
-             *        We can determine the depth into which metadata need to be created from the modification
-            *        -- if it does not have children, no need to bother with metadata.
-             */
-            return TreeNodeFactory.createTreeNode(modification.getWrittenValue(), version);
-        }
-
-        @Override
-        public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
-            if (child instanceof NodeIdentifier) {
-                return entryStrategy;
-            }
-            return Optional.absent();
-        }
-
-        @Override
-        protected void verifyWrittenStructure(final NormalizedNode<?, ?> writtenValue) {
-
-        }
-
-        @Override
-        protected void checkSubtreeModificationApplicable(final YangInstanceIdentifier path, final NodeModification modification,
-                final Optional<TreeNode> current) throws IncorrectDataStructureException {
-            throw new IncorrectDataStructureException(path, "Subtree modification is not allowed.");
-        }
-    }
 }