Add predicate-free NodeIdentifierWithPredicates constructor
[yangtools.git] / yang / yang-data-impl / src / main / java / org / opendaylight / yangtools / yang / data / impl / schema / tree / InMemoryDataTreeModification.java
index 0a137ab3b15eec6f97d7a2ea5dee0c22266c9088..54a3b5a587bb30a56f4fc162b6a69a840f565efb 100644 (file)
@@ -7,28 +7,28 @@
  */
 package org.opendaylight.yangtools.yang.data.impl.schema.tree;
 
-import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import java.util.Collection;
 import java.util.Map.Entry;
+import java.util.Optional;
 import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
 import javax.annotation.Nonnull;
-import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 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.NormalizedNodes;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.CursorAwareDataTreeModification;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModificationCursor;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.StoreTreeNodes;
 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.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-final class InMemoryDataTreeModification extends AbstractCursorAware implements CursorAwareDataTreeModification {
+final class InMemoryDataTreeModification extends AbstractCursorAware implements CursorAwareDataTreeModification,
+        SchemaContextProvider {
     private static final AtomicIntegerFieldUpdater<InMemoryDataTreeModification> SEALED_UPDATER =
             AtomicIntegerFieldUpdater.newUpdater(InMemoryDataTreeModification.class, "sealed");
     private static final Logger LOG = LoggerFactory.getLogger(InMemoryDataTreeModification.class);
@@ -40,7 +40,8 @@ final class InMemoryDataTreeModification extends AbstractCursorAware implements
 
     private volatile int sealed = 0;
 
-    InMemoryDataTreeModification(final InMemoryDataTreeSnapshot snapshot, final RootModificationApplyOperation resolver) {
+    InMemoryDataTreeModification(final InMemoryDataTreeSnapshot snapshot,
+            final RootModificationApplyOperation resolver) {
         this.snapshot = Preconditions.checkNotNull(snapshot);
         this.strategyTree = Preconditions.checkNotNull(resolver).snapshot();
         this.rootNode = ModifiedNode.createUnmodified(snapshot.getRootNode(), strategyTree.getChildPolicy());
@@ -65,6 +66,11 @@ final class InMemoryDataTreeModification extends AbstractCursorAware implements
         return strategyTree;
     }
 
+    @Override
+    public SchemaContext getSchemaContext() {
+        return snapshot.getSchemaContext();
+    }
+
     @Override
     public void write(final YangInstanceIdentifier path, final NormalizedNode<?, ?> data) {
         checkSealed();
@@ -102,11 +108,12 @@ final class InMemoryDataTreeModification extends AbstractCursorAware implements
         if (result.isPresent()) {
             final NormalizedNode<?, ?> data = result.get().getData();
             return NormalizedNodes.findNode(key, data, path);
-        } else {
-            return Optional.absent();
         }
+
+        return Optional.empty();
     }
 
+    @SuppressWarnings("checkstyle:illegalCatch")
     private Optional<TreeNode> resolveSnapshot(final YangInstanceIdentifier path, final ModifiedNode modification) {
         final Optional<TreeNode> potentialSnapshot = modification.getSnapshot();
         if (potentialSnapshot != null) {
@@ -131,7 +138,7 @@ final class InMemoryDataTreeModification extends AbstractCursorAware implements
         LOG.trace("Resolving modification apply strategy for {}", path);
 
         upgradeIfPossible();
-        return StoreTreeNodes.<ModificationApplyOperation>findNodeChecked(strategyTree, path);
+        return StoreTreeNodes.findNodeChecked(strategyTree, path);
     }
 
     private OperationWithModification resolveModificationFor(final YangInstanceIdentifier path) {
@@ -150,15 +157,15 @@ final class InMemoryDataTreeModification extends AbstractCursorAware implements
         ModificationApplyOperation operation = strategyTree;
         ModifiedNode modification = rootNode;
 
-        int i = 1;
-        for(final PathArgument pathArg : path.getPathArguments()) {
+        int depth = 1;
+        for (final PathArgument pathArg : path.getPathArguments()) {
             final Optional<ModificationApplyOperation> potential = operation.getChild(pathArg);
             if (!potential.isPresent()) {
                 throw new SchemaValidationFailedException(String.format("Child %s is not present in schema tree.",
-                        path.getAncestor(i)));
+                        path.getAncestor(depth)));
             }
             operation = potential.get();
-            ++i;
+            ++depth;
 
             modification = modification.modifyChild(pathArg, operation, version);
         }
@@ -176,7 +183,7 @@ final class InMemoryDataTreeModification extends AbstractCursorAware implements
     }
 
     @Override
-    public DataTreeModification newModification() {
+    public InMemoryDataTreeModification newModification() {
         Preconditions.checkState(sealed == 1, "Attempted to chain on an unsealed modification");
 
         if (rootNode.getOperation() == LogicalOperation.NONE) {
@@ -190,9 +197,11 @@ final class InMemoryDataTreeModification extends AbstractCursorAware implements
          */
         final TreeNode originalSnapshotRoot = snapshot.getRootNode();
         final Optional<TreeNode> tempRoot = strategyTree.apply(rootNode, Optional.of(originalSnapshotRoot), version);
-        Preconditions.checkState(tempRoot.isPresent(), "Data tree root is not present, possibly removed by previous modification");
+        Preconditions.checkState(tempRoot.isPresent(),
+            "Data tree root is not present, possibly removed by previous modification");
 
-        final InMemoryDataTreeSnapshot tempTree = new InMemoryDataTreeSnapshot(snapshot.getSchemaContext(), tempRoot.get(), strategyTree);
+        final InMemoryDataTreeSnapshot tempTree = new InMemoryDataTreeSnapshot(snapshot.getSchemaContext(),
+            tempRoot.get(), strategyTree);
         return tempTree.newModification();
     }
 
@@ -217,28 +226,28 @@ final class InMemoryDataTreeModification extends AbstractCursorAware implements
 
     private static void applyNode(final DataTreeModificationCursor cursor, final ModifiedNode node) {
         switch (node.getOperation()) {
-        case NONE:
-            break;
-        case DELETE:
-            cursor.delete(node.getIdentifier());
-            break;
-        case MERGE:
-            cursor.merge(node.getIdentifier(), node.getWrittenValue());
-            applyChildren(cursor, node);
-            break;
-        case TOUCH:
-            // TODO: we could improve efficiency of cursor use if we could understand
-            //       nested TOUCH operations. One way of achieving that would be a proxy
-            //       cursor, which would keep track of consecutive enter and exit calls
-            //       and coalesce them.
-            applyChildren(cursor, node);
-            break;
-        case WRITE:
-            cursor.write(node.getIdentifier(), node.getWrittenValue());
-            applyChildren(cursor, node);
-            break;
-        default:
-            throw new IllegalArgumentException("Unhandled node operation " + node.getOperation());
+            case NONE:
+                break;
+            case DELETE:
+                cursor.delete(node.getIdentifier());
+                break;
+            case MERGE:
+                cursor.merge(node.getIdentifier(), node.getWrittenValue());
+                applyChildren(cursor, node);
+                break;
+            case TOUCH:
+                // TODO: we could improve efficiency of cursor use if we could understand
+                //       nested TOUCH operations. One way of achieving that would be a proxy
+                //       cursor, which would keep track of consecutive enter and exit calls
+                //       and coalesce them.
+                applyChildren(cursor, node);
+                break;
+            case WRITE:
+                cursor.write(node.getIdentifier(), node.getWrittenValue());
+                applyChildren(cursor, node);
+                break;
+            default:
+                throw new IllegalArgumentException("Unhandled node operation " + node.getOperation());
         }
     }
 
@@ -254,15 +263,18 @@ final class InMemoryDataTreeModification extends AbstractCursorAware implements
             "Instance identifier references %s but data identifier is %s", arg, data.getIdentifier());
     }
 
-    private static void checkIdentifierReferencesData(final YangInstanceIdentifier path, final NormalizedNode<?, ?> data) {
+    private void checkIdentifierReferencesData(final YangInstanceIdentifier path,
+            final NormalizedNode<?, ?> data) {
+        final PathArgument arg;
+
         if (!path.isEmpty()) {
-            final PathArgument lastArg = path.getLastPathArgument();
-            Preconditions.checkArgument(lastArg != null, "Instance identifier %s has invalid null path argument", path);
-            checkIdentifierReferencesData(lastArg, data);
+            arg = path.getLastPathArgument();
+            Preconditions.checkArgument(arg != null, "Instance identifier %s has invalid null path argument", path);
         } else {
-            final QName type = data.getNodeType();
-            Preconditions.checkArgument(SchemaContext.NAME.equals(type), "Incorrect name %s of root node", type);
+            arg = rootNode.getIdentifier();
         }
+
+        checkIdentifierReferencesData(arg, data);
     }
 
     @Override