BUG-509: migrate to TreeNodes 46/7346/2
authorRobert Varga <rovarga@cisco.com>
Thu, 22 May 2014 20:58:55 +0000 (22:58 +0200)
committerRobert Varga <rovarga@cisco.com>
Fri, 23 May 2014 10:00:49 +0000 (12:00 +0200)
This patch performs the switchover to SPI-provided TreeNodes. It also
extracts the information needed for checking applicability of a
modification into a separate interface. Also adds some documentation in
the non-trivial write+merge path.

Change-Id: I83f5ca30bff21774759f9b675b19b6e9622076a2
Signed-off-by: Robert Varga <rovarga@cisco.com>
17 files changed:
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/AlwaysFailOperation.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTree.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeCandidate.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeFactory.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeModification.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeSnapshot.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ModificationApplyOperation.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ModifiedNode.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/NodeModification.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/NoopDataTreeCandidate.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/NormalizedNodeContainerModificationStrategy.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/OperationWithModification.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/SchemaAwareApplyOperation.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/StoreMetadataNode.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/StoreNodeCompositeBuilder.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ValueNodeModificationStrategy.java
opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ModificationMetadataTreeTest.java

index 5934fd6246c1ce6c74392d7e39b17b486d2c4309..7f66f7ff7e54090a9b101246c14cba338ba09403 100644 (file)
@@ -1,5 +1,6 @@
 package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
 
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
 
@@ -14,13 +15,13 @@ import com.google.common.primitives.UnsignedLong;
  */
 final class AlwaysFailOperation implements ModificationApplyOperation {
     @Override
-    public Optional<StoreMetadataNode> apply(final NodeModification modification,
-            final Optional<StoreMetadataNode> storeMeta, final UnsignedLong subtreeVersion) {
+    public Optional<TreeNode> apply(final ModifiedNode modification,
+            final Optional<TreeNode> storeMeta, final UnsignedLong subtreeVersion) {
         throw new IllegalStateException("Schema Context is not available.");
     }
 
     @Override
-    public void checkApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional<StoreMetadataNode> storeMetadata) {
+    public void checkApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional<TreeNode> storeMetadata) {
         throw new IllegalStateException("Schema Context is not available.");
     }
 
@@ -30,7 +31,7 @@ final class AlwaysFailOperation implements ModificationApplyOperation {
     }
 
     @Override
-    public void verifyStructure(final NodeModification modification) {
+    public void verifyStructure(final ModifiedNode modification) {
         throw new IllegalStateException("Schema Context is not available.");
     }
 }
\ No newline at end of file
index f04e379dd95824dd965c0ac8c5c998d9f0dafd83..ae71ed9adfdb43ac3d53f92313cf3747c2f4c11b 100644 (file)
@@ -16,6 +16,7 @@ import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeCandidate;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeModification;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreUtils;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.slf4j.Logger;
@@ -34,9 +35,9 @@ final class InMemoryDataTree implements DataTree {
     private final ReadWriteLock rwLock = new ReentrantReadWriteLock(true);
     private ModificationApplyOperation applyOper = new AlwaysFailOperation();
     private SchemaContext currentSchemaContext;
-    private StoreMetadataNode rootNode;
+    private TreeNode rootNode;
 
-    public InMemoryDataTree(StoreMetadataNode rootNode, final SchemaContext schemaContext) {
+    public InMemoryDataTree(final TreeNode rootNode, final SchemaContext schemaContext) {
         this.rootNode = Preconditions.checkNotNull(rootNode);
 
         if (schemaContext != null) {
@@ -80,28 +81,27 @@ final class InMemoryDataTree implements DataTree {
     }
 
     @Override
-    public void validate(DataTreeModification modification) throws DataPreconditionFailedException {
+    public void validate(final DataTreeModification modification) throws DataPreconditionFailedException {
         Preconditions.checkArgument(modification instanceof InMemoryDataTreeModification, "Invalid modification class %s", modification.getClass());
 
         final InMemoryDataTreeModification m = (InMemoryDataTreeModification)modification;
-        m.getStrategy().checkApplicable(PUBLIC_ROOT_PATH, m.getRootModification(), Optional.of(rootNode));
+        m.getStrategy().checkApplicable(PUBLIC_ROOT_PATH, m.getRootModification(), Optional.<TreeNode>of(rootNode));
     }
 
     @Override
-    public synchronized DataTreeCandidate prepare(DataTreeModification modification) {
+    public synchronized DataTreeCandidate prepare(final DataTreeModification modification) {
         Preconditions.checkArgument(modification instanceof InMemoryDataTreeModification, "Invalid modification class %s", modification.getClass());
 
         final InMemoryDataTreeModification m = (InMemoryDataTreeModification)modification;
-        final NodeModification root = m.getRootModification();
+        final ModifiedNode root = m.getRootModification();
 
-        if (root.getModificationType() == ModificationType.UNMODIFIED) {
+        if (root.getType() == ModificationType.UNMODIFIED) {
             return new NoopDataTreeCandidate(PUBLIC_ROOT_PATH, root);
         }
 
         rwLock.writeLock().lock();
         try {
-            // FIXME: rootNode needs to be a read-write snapshot here...
-            final Optional<StoreMetadataNode> newRoot = m.getStrategy().apply(m.getRootModification(), Optional.of(rootNode), StoreUtils.increase(rootNode.getSubtreeVersion()));
+            final Optional<TreeNode> newRoot = m.getStrategy().apply(m.getRootModification(), Optional.<TreeNode>of(rootNode), StoreUtils.increase(rootNode.getSubtreeVersion()));
             Preconditions.checkState(newRoot.isPresent(), "Apply strategy failed to produce root node");
             return new InMemoryDataTreeCandidate(PUBLIC_ROOT_PATH, root, rootNode, newRoot.get());
         } finally {
@@ -110,7 +110,7 @@ final class InMemoryDataTree implements DataTree {
     }
 
     @Override
-    public synchronized void commit(DataTreeCandidate candidate) {
+    public synchronized void commit(final DataTreeCandidate candidate) {
         if (candidate instanceof NoopDataTreeCandidate) {
             return;
         }
@@ -118,7 +118,7 @@ final class InMemoryDataTree implements DataTree {
         Preconditions.checkArgument(candidate instanceof InMemoryDataTreeCandidate, "Invalid candidate class %s", candidate.getClass());
         final InMemoryDataTreeCandidate c = (InMemoryDataTreeCandidate)candidate;
 
-        LOG.debug("Updating Store snapshot version: {} with version:{}", rootNode.getSubtreeVersion(), c.getAfterRoot().getSubtreeVersion());
+        LOG.debug("Updating datastore from {} to {}", rootNode, c.getAfterRoot());
 
         if (LOG.isTraceEnabled()) {
             LOG.trace("Data Tree is {}", StoreUtils.toStringTree(c.getAfterRoot().getData()));
index 72562f0a72bd218518a6a2cc0441c1f66af9e4be..bafea6bd9770c25c3e3f74d87cc9a60ebde4e200 100644 (file)
@@ -2,6 +2,7 @@ package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
 
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeCandidateNode;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
@@ -13,38 +14,42 @@ import com.google.common.collect.Iterables;
 
 final class InMemoryDataTreeCandidate extends AbstractDataTreeCandidate {
     private static abstract class AbstractNode implements DataTreeCandidateNode {
-        private final StoreMetadataNode newMeta;
-        private final StoreMetadataNode oldMeta;
-        private final NodeModification mod;
+        private final ModifiedNode mod;
+        private final TreeNode newMeta;
+        private final TreeNode oldMeta;
 
-        protected AbstractNode(final NodeModification mod,
-                final StoreMetadataNode oldMeta, final StoreMetadataNode newMeta) {
+        protected AbstractNode(final ModifiedNode mod,
+                final TreeNode oldMeta, final TreeNode newMeta) {
             this.newMeta = newMeta;
             this.oldMeta = oldMeta;
             this.mod = Preconditions.checkNotNull(mod);
         }
 
-        protected final NodeModification getMod() {
+        protected final ModifiedNode getMod() {
             return mod;
         }
 
-        protected final StoreMetadataNode getNewMeta() {
+        protected final TreeNode getNewMeta() {
             return newMeta;
         }
 
-        protected final StoreMetadataNode getOldMeta() {
+        protected final TreeNode getOldMeta() {
             return oldMeta;
         }
 
-        private static final StoreMetadataNode childMeta(final StoreMetadataNode parent, final PathArgument id) {
-            return parent == null ? null : parent.getChild(id).orNull();
+        private static final TreeNode childMeta(final TreeNode parent, final PathArgument id) {
+            if (parent != null) {
+                return parent.getChild(id).orNull();
+            } else {
+                return null;
+            }
         }
 
         @Override
         public Iterable<DataTreeCandidateNode> getChildNodes() {
-            return Iterables.transform(mod.getModifications(), new Function<NodeModification, DataTreeCandidateNode>() {
+            return Iterables.transform(mod.getChildren(), new Function<ModifiedNode, DataTreeCandidateNode>() {
                 @Override
-                public DataTreeCandidateNode apply(final NodeModification input) {
+                public DataTreeCandidateNode apply(final ModifiedNode input) {
                     final PathArgument id = input.getIdentifier();
                     return new ChildNode(input, childMeta(oldMeta, id), childMeta(newMeta, id));
                 }
@@ -53,14 +58,15 @@ final class InMemoryDataTreeCandidate extends AbstractDataTreeCandidate {
 
         @Override
         public ModificationType getModificationType() {
-            return mod.getModificationType();
+            return mod.getType();
         }
 
-        private Optional<NormalizedNode<?, ?>> optionalData(StoreMetadataNode meta) {
-            if (meta == null) {
+        private Optional<NormalizedNode<?, ?>> optionalData(final TreeNode meta) {
+            if (meta != null) {
+                return Optional.<NormalizedNode<?,?>>of(meta.getData());
+            } else {
                 return Optional.absent();
             }
-            return Optional.<NormalizedNode<?,?>>of(meta.getData());
         }
 
         @Override
@@ -75,7 +81,7 @@ final class InMemoryDataTreeCandidate extends AbstractDataTreeCandidate {
     }
 
     private static final class ChildNode extends AbstractNode {
-        public ChildNode(NodeModification mod, StoreMetadataNode oldMeta, StoreMetadataNode newMeta) {
+        public ChildNode(final ModifiedNode mod, final TreeNode oldMeta, final TreeNode newMeta) {
             super(mod, oldMeta, newMeta);
         }
 
@@ -86,7 +92,7 @@ final class InMemoryDataTreeCandidate extends AbstractDataTreeCandidate {
     }
 
     private static final class RootNode extends AbstractNode {
-        public RootNode(NodeModification mod, StoreMetadataNode oldMeta, StoreMetadataNode newMeta) {
+        public RootNode(final ModifiedNode mod, final TreeNode oldMeta, final TreeNode newMeta) {
             super(mod, oldMeta, newMeta);
         }
 
@@ -98,17 +104,17 @@ final class InMemoryDataTreeCandidate extends AbstractDataTreeCandidate {
 
     private final RootNode root;
 
-    InMemoryDataTreeCandidate(final InstanceIdentifier rootPath, final NodeModification modificationRoot,
-            final StoreMetadataNode oldRoot, final StoreMetadataNode newRoot) {
+    InMemoryDataTreeCandidate(final InstanceIdentifier rootPath, final ModifiedNode modificationRoot,
+            final TreeNode beforeRoot, final TreeNode afterRoot) {
         super(rootPath);
-        this.root = new RootNode(modificationRoot, oldRoot, newRoot);
+        this.root = new RootNode(modificationRoot, beforeRoot, afterRoot);
     }
 
-    StoreMetadataNode getAfterRoot() {
+    TreeNode getAfterRoot() {
         return root.getNewMeta();
     }
 
-    StoreMetadataNode getBeforeRoot() {
+    TreeNode getBeforeRoot() {
         return root.getOldMeta();
     }
 
index 7614611ab287913e4efa2b2a88e2fe02c393c946..82ffad507d4a8490efd6abd0aaedc8ca0c1edeee 100644 (file)
@@ -1,35 +1,38 @@
 package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
 
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeFactory;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNodeFactory;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
+import com.google.common.primitives.UnsignedLong;
+
 /**
  * A factory for creating in-memory data trees.
  */
 public final class InMemoryDataTreeFactory implements DataTreeFactory {
-       private static final InMemoryDataTreeFactory INSTANCE = new InMemoryDataTreeFactory();
+    private static final InMemoryDataTreeFactory INSTANCE = new InMemoryDataTreeFactory();
 
-       private InMemoryDataTreeFactory() {
-               // Never instantiated externally
-       }
+    private InMemoryDataTreeFactory() {
+        // Never instantiated externally
+    }
 
-       @Override
-       public InMemoryDataTree create() {
-               final NodeIdentifier root = new NodeIdentifier(SchemaContext.NAME);
-               final NormalizedNode<?, ?> data = Builders.containerBuilder().withNodeIdentifier(root).build();
+    @Override
+    public InMemoryDataTree create() {
+        final NodeIdentifier root = new NodeIdentifier(SchemaContext.NAME);
+        final NormalizedNode<?, ?> data = Builders.containerBuilder().withNodeIdentifier(root).build();
 
-               return new InMemoryDataTree(StoreMetadataNode.createEmpty(data), null);
-       }
+        return new InMemoryDataTree(TreeNodeFactory.createTreeNode(data, UnsignedLong.ZERO), null);
+    }
 
-       /**
-        * Get an instance of this factory. This method cannot fail.
-        *
-        * @return Data tree factory instance.
-        */
-       public static final InMemoryDataTreeFactory getInstance() {
-               return INSTANCE;
-       }
+    /**
+     * Get an instance of this factory. This method cannot fail.
+     *
+     * @return Data tree factory instance.
+     */
+    public static final InMemoryDataTreeFactory getInstance() {
+        return INSTANCE;
+    }
 }
index 7d0c81e39de8efe564c33925280c9dbb9c71ff22..fcb3ae0a10cf9028193dcdb60cea8a3a432664b3 100644 (file)
@@ -15,6 +15,7 @@ import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeModification;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreUtils;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.TreeNodeUtils;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
@@ -39,15 +40,15 @@ final class InMemoryDataTreeModification implements DataTreeModification {
 
     private final ModificationApplyOperation strategyTree;
     private final InMemoryDataTreeSnapshot snapshot;
-    private final NodeModification rootNode;
+    private final ModifiedNode rootNode;
 
     InMemoryDataTreeModification(final InMemoryDataTreeSnapshot snapshot, final ModificationApplyOperation resolver) {
         this.snapshot = Preconditions.checkNotNull(snapshot);
         this.strategyTree = Preconditions.checkNotNull(resolver);
-        this.rootNode = NodeModification.createUnmodified(snapshot.getRootNode());
+        this.rootNode = ModifiedNode.createUnmodified(snapshot.getRootNode());
     }
 
-    NodeModification getRootModification() {
+    ModifiedNode getRootModification() {
         return rootNode;
     }
 
@@ -93,11 +94,11 @@ final class InMemoryDataTreeModification implements DataTreeModification {
          * the requested path which has been modified. If no such node exists,
          * we use the node itself.
          */
-        final Entry<InstanceIdentifier, NodeModification> entry = TreeNodeUtils.findClosestsOrFirstMatch(rootNode, path, NodeModification.IS_TERMINAL_PREDICATE);
+        final Entry<InstanceIdentifier, ModifiedNode> entry = TreeNodeUtils.findClosestsOrFirstMatch(rootNode, path, ModifiedNode.IS_TERMINAL_PREDICATE);
         final InstanceIdentifier key = entry.getKey();
-        final NodeModification mod = entry.getValue();
+        final ModifiedNode mod = entry.getValue();
 
-        final Optional<StoreMetadataNode> result = resolveSnapshot(key, mod);
+        final Optional<TreeNode> result = resolveSnapshot(key, mod);
         if (result.isPresent()) {
             NormalizedNode<?, ?> data = result.get().getData();
             return NormalizedNodeUtils.findNode(key, data, path);
@@ -106,9 +107,9 @@ final class InMemoryDataTreeModification implements DataTreeModification {
         }
     }
 
-    private Optional<StoreMetadataNode> resolveSnapshot(final InstanceIdentifier path,
-            final NodeModification modification) {
-        final Optional<Optional<StoreMetadataNode>> potentialSnapshot = modification.getSnapshotCache();
+    private Optional<TreeNode> resolveSnapshot(final InstanceIdentifier path,
+            final ModifiedNode modification) {
+        final Optional<Optional<TreeNode>> potentialSnapshot = modification.getSnapshotCache();
         if(potentialSnapshot.isPresent()) {
             return potentialSnapshot.get();
         }
@@ -128,7 +129,7 @@ final class InMemoryDataTreeModification implements DataTreeModification {
     }
 
     private OperationWithModification resolveModificationFor(final InstanceIdentifier path) {
-        NodeModification modification = rootNode;
+        ModifiedNode modification = rootNode;
         // We ensure strategy is present.
         ModificationApplyOperation operation = resolveModificationStrategy(path);
         for (PathArgument pathArg : path.getPath()) {
index ce2d8c9bd43661e03e0d88cebca24805a62f3786..ee91e625187046f8aef429b756224959c58f3075 100644 (file)
@@ -1,6 +1,7 @@
 package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
 
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeSnapshot;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeUtils;
@@ -12,16 +13,16 @@ import com.google.common.base.Preconditions;
 final class InMemoryDataTreeSnapshot implements DataTreeSnapshot {
     private final ModificationApplyOperation applyOper;
     private final SchemaContext schemaContext;
-    private final StoreMetadataNode rootNode;
+    private final TreeNode rootNode;
 
-    InMemoryDataTreeSnapshot(final SchemaContext schemaContext, final StoreMetadataNode rootNode,
+    InMemoryDataTreeSnapshot(final SchemaContext schemaContext, final TreeNode rootNode,
             final ModificationApplyOperation applyOper) {
         this.schemaContext = Preconditions.checkNotNull(schemaContext);
         this.rootNode = Preconditions.checkNotNull(rootNode);
         this.applyOper = Preconditions.checkNotNull(applyOper);
     }
 
-    StoreMetadataNode getRootNode() {
+    TreeNode getRootNode() {
         return rootNode;
     }
 
index 5b4cd565e5cbf5e553fd640777a2a2599ed64b8c..a72d4fb5791e9b10a48151274a964ffafc48a2ce 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
 
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataPreconditionFailedException;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreTreeNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
 
@@ -17,7 +18,7 @@ import com.google.common.primitives.UnsignedLong;
 
 /**
  *
- * Operation responsible for applying {@link NodeModification} on tree.
+ * Operation responsible for applying {@link ModifiedNode} on tree.
  *
  * Operation is composite - operation on top level node consists of
  * suboperations on child nodes. This allows to walk operation hierarchy and
@@ -29,7 +30,7 @@ import com.google.common.primitives.UnsignedLong;
  * Implementations MUST expose all nested suboperations which operates on child
  * nodes expose via {@link #getChild(PathArgument)} method.
  * <li>Same suboperations SHOULD be used when invoked via
- * {@link #apply(NodeModification, Optional)} if applicable.
+ * {@link #apply(ModifiedNode, Optional)} if applicable.
  *
  *
  * Hierarchical composite operation which is responsible for applying
@@ -54,10 +55,10 @@ interface ModificationApplyOperation extends StoreTreeNode<ModificationApplyOper
      *             If it is not possible to apply Operation on provided Metadata
      *             node
      * @return new {@link StoreMetadataNode} if operation resulted in updating
-     *         node, {@link Optional#absent()} if {@link NodeModification}
+     *         node, {@link Optional#absent()} if {@link ModifiedNode}
      *         resulted in deletion of this node.
      */
-    Optional<StoreMetadataNode> apply(NodeModification modification, Optional<StoreMetadataNode> storeMeta, UnsignedLong subtreeVersion);
+    Optional<TreeNode> apply(ModifiedNode modification, Optional<TreeNode> storeMeta, UnsignedLong subtreeVersion);
 
     /**
      *
@@ -67,7 +68,7 @@ interface ModificationApplyOperation extends StoreTreeNode<ModificationApplyOper
      * @param modification to be verified.
      * @throws IllegalArgumentException If provided NodeModification does not adhere to the structure.
      */
-    void verifyStructure(NodeModification modification) throws IllegalArgumentException;
+    void verifyStructure(ModifiedNode modification) throws IllegalArgumentException;
 
     /**
      * Returns a suboperation for specified tree node
@@ -88,5 +89,5 @@ interface ModificationApplyOperation extends StoreTreeNode<ModificationApplyOper
      *         false if modification is no applicable
      * @throws DataPreconditionFailedException
      */
-    void checkApplicable(InstanceIdentifier path, NodeModification modification, Optional<StoreMetadataNode> current) throws DataPreconditionFailedException;
+    void checkApplicable(InstanceIdentifier path, NodeModification modification, Optional<TreeNode> current) throws DataPreconditionFailedException;
 }
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ModifiedNode.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ModifiedNode.java
new file mode 100644 (file)
index 0000000..0ff64e6
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import javax.annotation.concurrent.GuardedBy;
+
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreTreeNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
+import org.opendaylight.yangtools.concepts.Identifiable;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Predicate;
+
+/**
+ * Node Modification Node and Tree
+ *
+ * Tree which structurally resembles data tree and captures client modifications
+ * to the data store tree.
+ *
+ * This tree is lazily created and populated via {@link #modifyChild(PathArgument)}
+ * and {@link StoreMetadataNode} which represents original state {@link #getOriginal()}.
+ */
+final class ModifiedNode implements StoreTreeNode<ModifiedNode>, Identifiable<PathArgument>, NodeModification {
+
+    public static final Predicate<ModifiedNode> IS_TERMINAL_PREDICATE = new Predicate<ModifiedNode>() {
+        @Override
+        public boolean apply(final ModifiedNode input) {
+            switch (input.getType()) {
+            case DELETE:
+            case MERGE:
+            case WRITE:
+                return true;
+            case SUBTREE_MODIFIED:
+            case UNMODIFIED:
+                return false;
+            }
+
+            throw new IllegalArgumentException(String.format("Unhandled modification type %s", input.getType()));
+        }
+    };
+    private final PathArgument identifier;
+    private ModificationType modificationType = ModificationType.UNMODIFIED;
+
+
+    private final Optional<TreeNode> original;
+
+    private NormalizedNode<?, ?> value;
+
+    private Optional<TreeNode> snapshotCache;
+
+    private final Map<PathArgument, ModifiedNode> childModification;
+
+    @GuardedBy("this")
+    private boolean sealed = false;
+
+    private ModifiedNode(final PathArgument identifier, final Optional<TreeNode> original) {
+        this.identifier = identifier;
+        this.original = original;
+        childModification = new LinkedHashMap<>();
+    }
+
+    /**
+     *
+     *
+     * @return
+     */
+    public NormalizedNode<?, ?> getWrittenValue() {
+        return value;
+    }
+
+    @Override
+    public PathArgument getIdentifier() {
+        return identifier;
+    }
+
+    /**
+     *
+     * Returns original store metadata
+     * @return original store metadata
+     */
+    @Override
+    public final Optional<TreeNode> getOriginal() {
+        return original;
+    }
+
+    /**
+     * Returns modification type
+     *
+     * @return modification type
+     */
+    @Override
+    public final ModificationType getType() {
+        return modificationType;
+    }
+
+    /**
+     *
+     * Returns child modification if child was modified
+     *
+     * @return Child modification if direct child or it's subtree
+     *  was modified.
+     *
+     */
+    @Override
+    public Optional<ModifiedNode> getChild(final PathArgument child) {
+        return Optional.<ModifiedNode> fromNullable(childModification.get(child));
+    }
+
+    /**
+     *
+     * Returns child modification if child was modified, creates {@link ModifiedNode}
+     * for child otherwise.
+     *
+     * If this node's {@link ModificationType} is {@link ModificationType#UNMODIFIED}
+     * changes modification type to {@link ModificationType#SUBTREE_MODIFIED}
+     *
+     * @param child
+     * @return {@link ModifiedNode} for specified child, with {@link #getOriginal()}
+     *         containing child metadata if child was present in original data.
+     */
+    public synchronized ModifiedNode modifyChild(final PathArgument child) {
+        checkSealed();
+        clearSnapshot();
+        if (modificationType == ModificationType.UNMODIFIED) {
+            updateModificationType(ModificationType.SUBTREE_MODIFIED);
+        }
+        final ModifiedNode potential = childModification.get(child);
+        if (potential != null) {
+            return potential;
+        }
+
+        final Optional<TreeNode> currentMetadata;
+        if (original.isPresent()) {
+            final TreeNode orig = original.get();
+            currentMetadata = orig.getChild(child);
+        } else {
+            currentMetadata = Optional.absent();
+        }
+
+        ModifiedNode newlyCreated = new ModifiedNode(child, currentMetadata);
+        childModification.put(child, newlyCreated);
+        return newlyCreated;
+    }
+
+    /**
+     *
+     * Returns all recorded direct child modification
+     *
+     * @return all recorded direct child modifications
+     */
+    @Override
+    public Iterable<ModifiedNode> getChildren() {
+        return childModification.values();
+    }
+
+    /**
+     *
+     * Records a delete for associated node.
+     *
+     */
+    public synchronized void delete() {
+        checkSealed();
+        clearSnapshot();
+        updateModificationType(ModificationType.DELETE);
+        childModification.clear();
+        this.value = null;
+    }
+
+    /**
+     *
+     * Records a write for associated node.
+     *
+     * @param value
+     */
+    public synchronized void write(final NormalizedNode<?, ?> value) {
+        checkSealed();
+        clearSnapshot();
+        updateModificationType(ModificationType.WRITE);
+        childModification.clear();
+        this.value = value;
+    }
+
+    public synchronized void merge(final NormalizedNode<?, ?> data) {
+        checkSealed();
+        clearSnapshot();
+        updateModificationType(ModificationType.MERGE);
+        // FIXME: Probably merge with previous value.
+        this.value = data;
+    }
+
+    @GuardedBy("this")
+    private void checkSealed() {
+        Preconditions.checkState(!sealed, "Node Modification is sealed. No further changes allowed.");
+    }
+
+    public synchronized void seal() {
+        sealed = true;
+        clearSnapshot();
+        for(ModifiedNode child : childModification.values()) {
+            child.seal();
+        }
+    }
+
+    private void clearSnapshot() {
+        snapshotCache = null;
+    }
+
+    public Optional<TreeNode> storeSnapshot(final Optional<TreeNode> snapshot) {
+        snapshotCache = snapshot;
+        return snapshot;
+    }
+
+    public Optional<Optional<TreeNode>> getSnapshotCache() {
+        return Optional.fromNullable(snapshotCache);
+    }
+
+    @GuardedBy("this")
+    private void updateModificationType(final ModificationType type) {
+        modificationType = type;
+        clearSnapshot();
+    }
+
+    @Override
+    public String toString() {
+        return "NodeModification [identifier=" + identifier + ", modificationType="
+                + modificationType + ", childModification=" + childModification + "]";
+    }
+
+    public static ModifiedNode createUnmodified(final TreeNode metadataTree) {
+        return new ModifiedNode(metadataTree.getIdentifier(), Optional.of(metadataTree));
+    }
+}
index fccc1ed5be7634dc20df14b8888682ebbd992e8c..2639d050efe28b8b0903636e987b5c134e79c922 100644 (file)
  */
 package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
 
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-import javax.annotation.concurrent.GuardedBy;
-
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreTreeNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
 import org.opendaylight.yangtools.concepts.Identifiable;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 
 import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-
-/**
- * Node Modification Node and Tree
- *
- * Tree which structurally resembles data tree and captures client modifications
- * to the data store tree.
- *
- * This tree is lazily created and populated via {@link #modifyChild(PathArgument)}
- * and {@link StoreMetadataNode} which represents original state {@link #getOriginal()}.
- */
-final class NodeModification implements StoreTreeNode<NodeModification>, Identifiable<PathArgument> {
-
-    public static final Predicate<NodeModification> IS_TERMINAL_PREDICATE = new Predicate<NodeModification>() {
-        @Override
-        public boolean apply(final NodeModification input) {
-            return input.getModificationType() == ModificationType.WRITE //
-                    || input.getModificationType() == ModificationType.DELETE //
-                    || input.getModificationType() == ModificationType.MERGE;
-        }
-    };
-    private final PathArgument identifier;
-    private ModificationType modificationType = ModificationType.UNMODIFIED;
-
-
-    private final Optional<StoreMetadataNode> original;
-
-    private NormalizedNode<?, ?> value;
-
-    private Optional<StoreMetadataNode> snapshotCache;
-
-    private final Map<PathArgument, NodeModification> childModification;
-
-    @GuardedBy("this")
-    private boolean sealed = false;
-
-    protected NodeModification(final PathArgument identifier, final Optional<StoreMetadataNode> original) {
-        this.identifier = identifier;
-        this.original = original;
-        childModification = new LinkedHashMap<>();
-    }
-
-    /**
-     *
-     *
-     * @return
-     */
-    public NormalizedNode<?, ?> getWrittenValue() {
-        return value;
-    }
-
-    @Override
-    public PathArgument getIdentifier() {
-        return identifier;
-    }
-
-    /**
-     *
-     * Returns original store metadata
-     * @return original store metadata
-     */
-    public final Optional<StoreMetadataNode> getOriginal() {
-        return original;
-    }
-
-    /**
-     * Returns modification type
-     *
-     * @return modification type
-     */
-    public final ModificationType getModificationType() {
-        return modificationType;
-    }
-
-    /**
-     *
-     * Returns child modification if child was modified
-     *
-     * @return Child modification if direct child or it's subtree
-     *  was modified.
-     *
-     */
-    @Override
-    public Optional<NodeModification> getChild(final PathArgument child) {
-        return Optional.<NodeModification> fromNullable(childModification.get(child));
-    }
-
-    /**
-     *
-     * Returns child modification if child was modified, creates {@link NodeModification}
-     * for child otherwise.
-     *
-     * If this node's {@link ModificationType} is {@link ModificationType#UNMODIFIED}
-     * changes modification type to {@link ModificationType#SUBTREE_MODIFIED}
-     *
-     * @param child
-     * @return {@link NodeModification} for specified child, with {@link #getOriginal()}
-     *  containing child metadata if child was present in original data.
-     */
-    public synchronized NodeModification modifyChild(final PathArgument child) {
-        checkSealed();
-        clearSnapshot();
-        if(modificationType == ModificationType.UNMODIFIED) {
-            updateModificationType(ModificationType.SUBTREE_MODIFIED);
-        }
-        final NodeModification potential = childModification.get(child);
-        if (potential != null) {
-            return potential;
-        }
-        Optional<StoreMetadataNode> currentMetadata = Optional.absent();
-        if(original.isPresent()) {
-            currentMetadata = original.get().getChild(child);
-        }
-        NodeModification newlyCreated = new NodeModification(child,currentMetadata);
-        childModification.put(child, newlyCreated);
-        return newlyCreated;
-    }
-
-    /**
-     *
-     * Returns all recorded direct child modification
-     *
-     * @return all recorded direct child modifications
-     */
-    public Iterable<NodeModification> getModifications() {
-        return childModification.values();
-    }
-
-
-    /**
-     *
-     * Records a delete for associated node.
-     *
-     */
-    public synchronized void delete() {
-        checkSealed();
-        clearSnapshot();
-        updateModificationType(ModificationType.DELETE);
-        childModification.clear();
-        this.value = null;
-    }
-
-    /**
-     *
-     * Records a write for associated node.
-     *
-     * @param value
-     */
-    public synchronized void write(final NormalizedNode<?, ?> value) {
-        checkSealed();
-        clearSnapshot();
-        updateModificationType(ModificationType.WRITE);
-        childModification.clear();
-        this.value = value;
-    }
-
-    public synchronized void merge(final NormalizedNode<?, ?> data) {
-        checkSealed();
-        clearSnapshot();
-        updateModificationType(ModificationType.MERGE);
-        // FIXME: Probably merge with previous value.
-        this.value = data;
-    }
-
-    @GuardedBy("this")
-    private void checkSealed() {
-        Preconditions.checkState(!sealed, "Node Modification is sealed. No further changes allowed.");
-    }
-
-    public synchronized void seal() {
-        sealed = true;
-        clearSnapshot();
-        for(NodeModification child : childModification.values()) {
-            child.seal();
-        }
-    }
-
-    private void clearSnapshot() {
-        snapshotCache = null;
-    }
-
-    public Optional<StoreMetadataNode> storeSnapshot(final Optional<StoreMetadataNode> snapshot) {
-        snapshotCache = snapshot;
-        return snapshot;
-    }
-
-    public Optional<Optional<StoreMetadataNode>> getSnapshotCache() {
-        return Optional.fromNullable(snapshotCache);
-    }
-
-    public boolean hasAdditionalModifications() {
-        return !childModification.isEmpty();
-    }
-
-    @GuardedBy("this")
-    private void updateModificationType(final ModificationType type) {
-        modificationType = type;
-        clearSnapshot();
-    }
-
-    @Override
-    public String toString() {
-        return "NodeModification [identifier=" + identifier + ", modificationType="
-                + modificationType + ", childModification=" + childModification + "]";
-    }
-
-    public static NodeModification createUnmodified(final StoreMetadataNode metadataTree) {
-        return new NodeModification(metadataTree.getIdentifier(), Optional.of(metadataTree));
-    }
 
+interface NodeModification extends Identifiable<PathArgument> {
+    ModificationType getType();
+    Optional<TreeNode> getOriginal();
+    Iterable<? extends NodeModification> getChildren();
 }
index 8a467484141bf9631cd05b26ae09b85f1943d6fd..2ef85cbcb7e548cb6fa1ccd932e7dddbb651ace3 100644 (file)
@@ -46,9 +46,9 @@ final class NoopDataTreeCandidate extends AbstractDataTreeCandidate {
         }
     };
 
-    protected NoopDataTreeCandidate(final InstanceIdentifier rootPath, final NodeModification modificationRoot) {
+    protected NoopDataTreeCandidate(final InstanceIdentifier rootPath, final ModifiedNode modificationRoot) {
         super(rootPath);
-        Preconditions.checkArgument(modificationRoot.getModificationType() == ModificationType.UNMODIFIED);
+        Preconditions.checkArgument(modificationRoot.getType() == ModificationType.UNMODIFIED);
     }
 
     @Override
index 7ab840e0e05f760623d5eb29ead101db59a4b8d8..c5037bc0c64714cb10de717a6c46954f8d5cf78b 100644 (file)
@@ -16,6 +16,9 @@ import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreUtils;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.DataNodeContainerModificationStrategy.ListEntryModificationStrategy;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.ValueNodeModificationStrategy.LeafSetEntryModificationStrategy;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.MutableTreeNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNodeFactory;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
@@ -42,6 +45,7 @@ import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 
 import com.google.common.base.Optional;
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
 import com.google.common.primitives.UnsignedLong;
 
 abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareApplyOperation {
@@ -53,18 +57,18 @@ abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareAp
     }
 
     @Override
-    public void verifyStructure(final NodeModification modification) throws IllegalArgumentException {
-        if (modification.getModificationType() == ModificationType.WRITE) {
+    public void verifyStructure(final ModifiedNode modification) throws IllegalArgumentException {
+        if (modification.getType() == ModificationType.WRITE) {
 
         }
-        for (NodeModification childModification : modification.getModifications()) {
+        for (ModifiedNode childModification : modification.getChildren()) {
             resolveChildOperation(childModification.getIdentifier()).verifyStructure(childModification);
         }
     }
 
     @Override
     protected void checkWriteApplicable(final InstanceIdentifier path, final NodeModification modification,
-            final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
+            final Optional<TreeNode> current) throws DataPreconditionFailedException {
         // FIXME: Implement proper write check for replacement of node container
         //        prerequisite is to have transaction chain available for clients
         //        otherwise this will break chained writes to same node.
@@ -90,94 +94,110 @@ abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareAp
     }
 
     @Override
-    protected StoreMetadataNode applyWrite(final NodeModification modification,
-            final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
-
-        NormalizedNode<?, ?> newValue = modification.getWrittenValue();
-
+    protected TreeNode applyWrite(final ModifiedNode modification,
+            final Optional<TreeNode> currentMeta, final UnsignedLong subtreeVersion) {
         final UnsignedLong nodeVersion;
         if (currentMeta.isPresent()) {
-            nodeVersion = StoreUtils.increase(currentMeta.get().getNodeVersion());
+            nodeVersion = StoreUtils.increase(currentMeta.get().getVersion());
         } else {
             nodeVersion = subtreeVersion;
         }
 
-        final StoreMetadataNode newValueMeta = StoreMetadataNode.createRecursively(newValue, nodeVersion);
-        if (!modification.hasAdditionalModifications()) {
+        final NormalizedNode<?, ?> newValue = modification.getWrittenValue();
+        final TreeNode newValueMeta = TreeNodeFactory.createTreeNode(newValue, nodeVersion);
+
+        if (Iterables.isEmpty(modification.getChildren())) {
             return newValueMeta;
         }
 
+        /*
+         * This is where things get interesting. The user has performed a write and
+         * then she applied some more modifications to it. So we need to make sense
+         * of that an apply the operations on top of the written value. We could have
+         * done it during the write, but this operation is potentially expensive, so
+         * we have left it out of the fast path.
+         *
+         * 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.
+         */
+        final MutableTreeNode mutable = newValueMeta.mutable();
+        mutable.setSubtreeVersion(subtreeVersion);
+
         @SuppressWarnings("rawtypes")
-        NormalizedNodeContainerBuilder dataBuilder = createBuilder(newValue);
-        StoreNodeCompositeBuilder builder = StoreNodeCompositeBuilder.create(nodeVersion, dataBuilder) //
-                .setSubtreeVersion(subtreeVersion);
+        final NormalizedNodeContainerBuilder dataBuilder = createBuilder(newValue);
+
+        return mutateChildren(mutable, dataBuilder, nodeVersion, modification.getChildren());
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    private TreeNode mutateChildren(final MutableTreeNode meta, final NormalizedNodeContainerBuilder data,
+            final UnsignedLong nodeVersion, final Iterable<ModifiedNode> modifications) {
+
+        for (ModifiedNode mod : modifications) {
+            final PathArgument id = mod.getIdentifier();
+            final Optional<TreeNode> cm = meta.getChild(id);
+
+            Optional<TreeNode> result = resolveChildOperation(id).apply(mod, cm, nodeVersion);
+            if (result.isPresent()) {
+                final TreeNode tn = result.get();
+                meta.addChild(tn);
+                data.addChild(tn.getData());
+            } else {
+                meta.removeChild(id);
+                data.removeChild(id);
+            }
+        }
 
-        return mutateChildren(modification.getModifications(), newValueMeta, builder, nodeVersion);
+        meta.setData(data.build());
+        return meta.seal();
     }
 
     @Override
-    protected StoreMetadataNode applyMerge(final NodeModification modification, final StoreMetadataNode currentMeta,
+    protected TreeNode applyMerge(final ModifiedNode modification, final TreeNode currentMeta,
             final UnsignedLong subtreeVersion) {
         // For Node Containers - merge is same as subtree change - we only replace children.
         return applySubtreeChange(modification, currentMeta, subtreeVersion);
     }
 
     @Override
-    public StoreMetadataNode applySubtreeChange(final NodeModification modification,
-            final StoreMetadataNode currentMeta, final UnsignedLong subtreeVersion) {
+    public TreeNode applySubtreeChange(final ModifiedNode modification,
+            final TreeNode currentMeta, final UnsignedLong subtreeVersion) {
         // Bump subtree version to its new target
         final UnsignedLong updatedSubtreeVersion = StoreUtils.increase(currentMeta.getSubtreeVersion());
 
+        final MutableTreeNode newMeta = currentMeta.mutable();
+        newMeta.setSubtreeVersion(updatedSubtreeVersion);
+
         @SuppressWarnings("rawtypes")
         NormalizedNodeContainerBuilder dataBuilder = createBuilder(currentMeta.getData());
-        StoreNodeCompositeBuilder builder = StoreNodeCompositeBuilder.create(dataBuilder, currentMeta)
-                .setIdentifier(modification.getIdentifier())
-                .setSubtreeVersion(updatedSubtreeVersion);
 
-        return mutateChildren(modification.getModifications(), currentMeta, builder, updatedSubtreeVersion);
-    }
-
-    private StoreMetadataNode mutateChildren(final Iterable<NodeModification> modifications, final StoreMetadataNode meta,
-            final StoreNodeCompositeBuilder builder, final UnsignedLong nodeVersion) {
-
-        for (NodeModification mod : modifications) {
-            final PathArgument id = mod.getIdentifier();
-            final Optional<StoreMetadataNode> cm = meta.getChild(id);
-
-            Optional<StoreMetadataNode> result = resolveChildOperation(id).apply(mod, cm, nodeVersion);
-            if (result.isPresent()) {
-                builder.add(result.get());
-            } else {
-                builder.remove(id);
-            }
-        }
-
-        return builder.build();
+        return mutateChildren(newMeta, dataBuilder, updatedSubtreeVersion, modification.getChildren());
     }
 
     @Override
-    protected void checkSubtreeModificationApplicable(final InstanceIdentifier path,final NodeModification modification,
-            final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
+    protected void checkSubtreeModificationApplicable(final InstanceIdentifier path, final NodeModification modification,
+            final Optional<TreeNode> current) throws DataPreconditionFailedException {
         checkDataPrecondition(path, current.isPresent(), "Node was deleted by other transaction.");
-        checkChildPreconditions(path,modification,current);
-
+        checkChildPreconditions(path, modification, current);
     }
 
-    private void checkChildPreconditions(final InstanceIdentifier path, final NodeModification modification, final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
-        StoreMetadataNode currentMeta = current.get();
-        for (NodeModification childMod : modification.getModifications()) {
-            PathArgument childId = childMod.getIdentifier();
-            Optional<StoreMetadataNode> childMeta = currentMeta.getChild(childId);
+    private void checkChildPreconditions(final InstanceIdentifier path, final NodeModification modification, final Optional<TreeNode> current) throws DataPreconditionFailedException {
+        final TreeNode currentMeta = current.get();
+        for (NodeModification childMod : modification.getChildren()) {
+            final PathArgument childId = childMod.getIdentifier();
+            final Optional<TreeNode> childMeta = currentMeta.getChild(childId);
+
             InstanceIdentifier childPath = StoreUtils.append(path, childId);
-            resolveChildOperation(childId).checkApplicable(childPath,childMod, childMeta);
+            resolveChildOperation(childId).checkApplicable(childPath, childMod, childMeta);
         }
     }
 
     @Override
     protected void checkMergeApplicable(final InstanceIdentifier path, final NodeModification modification,
-            final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
+            final Optional<TreeNode> current) throws DataPreconditionFailedException {
         if(current.isPresent()) {
-            checkChildPreconditions(path,modification,current);
+            checkChildPreconditions(path, modification,current);
         }
     }
 
@@ -325,4 +345,4 @@ abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareAp
             return "UnorderedMapModificationStrategy [entry=" + entryStrategy + "]";
         }
     }
-}
\ No newline at end of file
+}
index fda8407a95ea842a7dc0c462cf3e7dda217d26c8..0a5fad3e8b485cf344fbeba19732996cdc45725e 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
 
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 
@@ -15,11 +16,11 @@ import com.google.common.primitives.UnsignedLong;
 
 final class OperationWithModification {
 
-    private final NodeModification modification;
+    private final ModifiedNode modification;
 
     private final ModificationApplyOperation applyOperation;
 
-    private OperationWithModification(final ModificationApplyOperation op, final NodeModification mod) {
+    private OperationWithModification(final ModificationApplyOperation op, final ModifiedNode mod) {
         this.modification = mod;
         this.applyOperation = op;
     }
@@ -35,7 +36,7 @@ final class OperationWithModification {
         return this;
     }
 
-    public NodeModification getModification() {
+    public ModifiedNode getModification() {
         return modification;
     }
 
@@ -43,12 +44,12 @@ final class OperationWithModification {
         return applyOperation;
     }
 
-    public Optional<StoreMetadataNode> apply(final Optional<StoreMetadataNode> data, final UnsignedLong subtreeVersion) {
+    public Optional<TreeNode> apply(final Optional<TreeNode> data, final UnsignedLong subtreeVersion) {
         return applyOperation.apply(modification, data, subtreeVersion);
     }
 
     public static OperationWithModification from(final ModificationApplyOperation operation,
-            final NodeModification modification) {
+            final ModifiedNode modification) {
         return new OperationWithModification(operation, modification);
 
     }
@@ -60,7 +61,7 @@ final class OperationWithModification {
     }
 
     public OperationWithModification forChild(final PathArgument childId) {
-        NodeModification childMod = modification.modifyChild(childId);
+        ModifiedNode childMod = modification.modifyChild(childId);
         Optional<ModificationApplyOperation> childOp = applyOperation.getChild(childId);
         return from(childOp.get(),childMod);
     }
index 7afc12caabc052fb5ac7809bee62b92c04751281..a0730e44daec0ae5bc5a11117140d398d0ab1c20 100644 (file)
@@ -20,6 +20,8 @@ import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.NormalizedNod
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.NormalizedNodeContainerModificationStrategy.OrderedMapModificationStrategy;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.NormalizedNodeContainerModificationStrategy.UnorderedLeafSetModificationStrategy;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.ValueNodeModificationStrategy.LeafModificationStrategy;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNodeFactory;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationIdentifier;
@@ -80,6 +82,13 @@ abstract class SchemaAwareApplyOperation implements ModificationApplyOperation {
         return null;
     }
 
+    public static boolean checkDataPrecondition(final InstanceIdentifier path, final boolean condition, final String message) throws DataPreconditionFailedException {
+        if(!condition) {
+            throw new DataPreconditionFailedException(path, message);
+        }
+        return condition;
+    }
+
     private static SchemaAwareApplyOperation fromListSchemaNode(final ListSchemaNode schemaNode) {
         List<QName> keyDefinition = schemaNode.getKeyDefinition();
         if (keyDefinition == null || keyDefinition.isEmpty()) {
@@ -100,9 +109,11 @@ abstract class SchemaAwareApplyOperation implements ModificationApplyOperation {
         }
     }
 
-    private static final void checkNotConflicting(final InstanceIdentifier path,final StoreMetadataNode original, final StoreMetadataNode current) throws DataPreconditionFailedException {
-        checkDataPrecondition(path, original.getNodeVersion().equals(current.getNodeVersion()),"Node was replaced by other transaction.");
-        checkDataPrecondition(path,original.getSubtreeVersion().equals(current.getSubtreeVersion()), "Node children was modified by other transaction");
+    private static final void checkNotConflicting(final InstanceIdentifier path, final TreeNode original, final TreeNode current) throws DataPreconditionFailedException {
+        checkDataPrecondition(path, original.getVersion().equals(current.getVersion()),
+                "Node was replaced by other transaction.");
+        checkDataPrecondition(path, original.getSubtreeVersion().equals(current.getSubtreeVersion()),
+                "Node children was modified by other transaction");
     }
 
     protected final ModificationApplyOperation resolveChildOperation(final PathArgument child) {
@@ -112,36 +123,36 @@ abstract class SchemaAwareApplyOperation implements ModificationApplyOperation {
     }
 
     @Override
-    public void verifyStructure(final NodeModification modification) throws IllegalArgumentException {
-        if (modification.getModificationType() == ModificationType.WRITE) {
+    public void verifyStructure(final ModifiedNode modification) throws IllegalArgumentException {
+        if (modification.getType() == ModificationType.WRITE) {
             verifyWrittenStructure(modification.getWrittenValue());
         }
     }
 
     @Override
-    public void checkApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
-        switch (modification.getModificationType()) {
+    public final void checkApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional<TreeNode> current) throws DataPreconditionFailedException {
+        switch (modification.getType()) {
         case DELETE:
             checkDeleteApplicable(modification, current);
         case SUBTREE_MODIFIED:
-            checkSubtreeModificationApplicable(path,modification, current);
+            checkSubtreeModificationApplicable(path, modification, current);
             return;
         case WRITE:
-            checkWriteApplicable(path,modification, current);
+            checkWriteApplicable(path, modification, current);
             return;
         case MERGE:
-            checkMergeApplicable(path,modification,current);
+            checkMergeApplicable(path, modification, current);
             return;
         case UNMODIFIED:
             return;
         default:
-            throw new UnsupportedOperationException("Suplied modification type "+modification.getModificationType()+ "is not supported.");
+            throw new UnsupportedOperationException("Suplied modification type "+ modification.getType()+ "is not supported.");
         }
 
     }
 
-    protected void checkMergeApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
-        Optional<StoreMetadataNode> original = modification.getOriginal();
+    protected void checkMergeApplicable(final InstanceIdentifier path, final NodeModification modification, final Optional<TreeNode> current) throws DataPreconditionFailedException {
+        Optional<TreeNode> original = modification.getOriginal();
         if (original.isPresent() && current.isPresent()) {
             /*
              * We need to do conflict detection only and only if the value of leaf changed
@@ -150,22 +161,21 @@ abstract class SchemaAwareApplyOperation implements ModificationApplyOperation {
              * leads to same data.
              */
             if(!original.get().getData().equals(current.get().getData())) {
-
-                checkNotConflicting(path,original.get(), current.get());
+                checkNotConflicting(path, original.get(), current.get());
             }
         }
     }
 
-    protected void checkWriteApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
-        Optional<StoreMetadataNode> original = modification.getOriginal();
+    protected void checkWriteApplicable(final InstanceIdentifier path, final NodeModification modification, final Optional<TreeNode> current) throws DataPreconditionFailedException {
+        Optional<TreeNode> original = modification.getOriginal();
         if (original.isPresent() && current.isPresent()) {
-            checkNotConflicting(path,original.get(), current.get());
+            checkNotConflicting(path, original.get(), current.get());
         } else if(original.isPresent()) {
             throw new DataPreconditionFailedException(path,"Node was deleted by other transaction.");
         }
     }
 
-    private void checkDeleteApplicable(final NodeModification modification, final Optional<StoreMetadataNode> current) {
+    private void checkDeleteApplicable(final NodeModification modification, final Optional<TreeNode> current) {
         // Delete is always applicable, we do not expose it to subclasses
         if (current.isPresent()) {
             LOG.trace("Delete operation turned to no-op on missing node {}", modification);
@@ -173,12 +183,12 @@ abstract class SchemaAwareApplyOperation implements ModificationApplyOperation {
     }
 
     @Override
-    public final Optional<StoreMetadataNode> apply(final NodeModification modification,
-            final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
+    public final Optional<TreeNode> apply(final ModifiedNode modification,
+            final Optional<TreeNode> currentMeta, final UnsignedLong subtreeVersion) {
 
-        switch (modification.getModificationType()) {
+        switch (modification.getType()) {
         case DELETE:
-            return modification.storeSnapshot(Optional.<StoreMetadataNode> absent());
+            return modification.storeSnapshot(Optional.<TreeNode> absent());
         case SUBTREE_MODIFIED:
             Preconditions.checkArgument(currentMeta.isPresent(), "Metadata not available for modification",
                     modification);
@@ -197,17 +207,17 @@ abstract class SchemaAwareApplyOperation implements ModificationApplyOperation {
         }
     }
 
-    protected abstract StoreMetadataNode applyMerge(NodeModification modification,
-            StoreMetadataNode currentMeta, UnsignedLong subtreeVersion);
+    protected abstract TreeNode applyMerge(ModifiedNode modification,
+            TreeNode currentMeta, UnsignedLong subtreeVersion);
 
-    protected abstract StoreMetadataNode applyWrite(NodeModification modification,
-            Optional<StoreMetadataNode> currentMeta, UnsignedLong subtreeVersion);
+    protected abstract TreeNode applyWrite(ModifiedNode modification,
+            Optional<TreeNode> currentMeta, UnsignedLong subtreeVersion);
 
-    protected abstract StoreMetadataNode applySubtreeChange(NodeModification modification,
-            StoreMetadataNode currentMeta, UnsignedLong subtreeVersion);
+    protected abstract TreeNode applySubtreeChange(ModifiedNode modification,
+            TreeNode currentMeta, UnsignedLong subtreeVersion);
 
-    protected abstract void checkSubtreeModificationApplicable(InstanceIdentifier path,final NodeModification modification,
-            final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException;
+    protected abstract void checkSubtreeModificationApplicable(InstanceIdentifier path, final NodeModification modification,
+            final Optional<TreeNode> current) throws DataPreconditionFailedException;
 
     protected abstract void verifyWrittenStructure(NormalizedNode<?, ?> writtenValue);
 
@@ -220,21 +230,21 @@ abstract class SchemaAwareApplyOperation implements ModificationApplyOperation {
         }
 
         @Override
-        protected StoreMetadataNode applyMerge(final NodeModification modification, final StoreMetadataNode currentMeta,
+        protected TreeNode applyMerge(final ModifiedNode modification, final TreeNode currentMeta,
                 final UnsignedLong subtreeVersion) {
             return applyWrite(modification, Optional.of(currentMeta), subtreeVersion);
         }
 
         @Override
-        protected StoreMetadataNode applySubtreeChange(final NodeModification modification,
-                final StoreMetadataNode currentMeta, final UnsignedLong subtreeVersion) {
+        protected TreeNode applySubtreeChange(final ModifiedNode modification,
+                final TreeNode currentMeta, final UnsignedLong subtreeVersion) {
             throw new UnsupportedOperationException("UnkeyedList does not support subtree change.");
         }
 
         @Override
-        protected StoreMetadataNode applyWrite(final NodeModification modification,
-                final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
-            return StoreMetadataNode.createRecursively(modification.getWrittenValue(), subtreeVersion);
+        protected TreeNode applyWrite(final ModifiedNode modification,
+                final Optional<TreeNode> currentMeta, final UnsignedLong subtreeVersion) {
+            return TreeNodeFactory.createTreeNode(modification.getWrittenValue(), subtreeVersion);
         }
 
         @Override
@@ -251,17 +261,9 @@ abstract class SchemaAwareApplyOperation implements ModificationApplyOperation {
         }
 
         @Override
-        protected void checkSubtreeModificationApplicable(final InstanceIdentifier path,final NodeModification modification,
-                final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
+        protected void checkSubtreeModificationApplicable(final InstanceIdentifier path, final NodeModification modification,
+                final Optional<TreeNode> current) throws DataPreconditionFailedException {
             throw new DataPreconditionFailedException(path, "Subtree modification is not allowed.");
         }
     }
-
-    public static boolean checkDataPrecondition(final InstanceIdentifier path, final boolean condition, final String message) throws DataPreconditionFailedException {
-        if(!condition) {
-            throw new DataPreconditionFailedException(path, message);
-        }
-        return condition;
-    }
-
 }
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/StoreMetadataNode.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/StoreMetadataNode.java
deleted file mode 100644 (file)
index 695a1f1..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
-
-import static com.google.common.base.Preconditions.checkState;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.opendaylight.yangtools.concepts.Identifiable;
-import org.opendaylight.yangtools.concepts.Immutable;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
-
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.primitives.UnsignedLong;
-
-class StoreMetadataNode implements Immutable, Identifiable<PathArgument> {
-    private final Map<PathArgument, StoreMetadataNode> children;
-    private final UnsignedLong nodeVersion;
-    private final UnsignedLong subtreeVersion;
-    private final NormalizedNode<?, ?> data;
-
-    /**
-     *
-     * @param data
-     * @param nodeVersion
-     * @param subtreeVersion
-     * @param children Map of children, must not be modified externally
-     */
-    private StoreMetadataNode(final NormalizedNode<?, ?> data, final UnsignedLong nodeVersion,
-            final UnsignedLong subtreeVersion, final Map<PathArgument, StoreMetadataNode> children) {
-        this.nodeVersion = Preconditions.checkNotNull(nodeVersion);
-        this.subtreeVersion = Preconditions.checkNotNull(subtreeVersion);
-        this.data = Preconditions.checkNotNull(data);
-        this.children = Preconditions.checkNotNull(children);
-    }
-
-    public static StoreMetadataNode createEmpty(final NormalizedNode<?, ?> data) {
-        return new StoreMetadataNode(data, UnsignedLong.ZERO, UnsignedLong.ZERO,
-                Collections.<PathArgument, StoreMetadataNode>emptyMap());
-    }
-
-    public static Builder builder(final UnsignedLong version) {
-        return new Builder(version);
-    }
-
-    public static Builder builder(final StoreMetadataNode node) {
-        return new Builder(node);
-    }
-
-    public UnsignedLong getNodeVersion() {
-        return this.nodeVersion;
-    }
-
-    @Override
-    public PathArgument getIdentifier() {
-        return data.getIdentifier();
-    }
-
-    public UnsignedLong getSubtreeVersion() {
-        return subtreeVersion;
-    }
-
-    public NormalizedNode<?, ?> getData() {
-        return this.data;
-    }
-
-    Optional<StoreMetadataNode> getChild(final PathArgument key) {
-        return Optional.fromNullable(children.get(key));
-    }
-
-    @Override
-    public String toString() {
-        return "StoreMetadataNode [identifier=" + getIdentifier() + ", nodeVersion=" + nodeVersion + "]";
-    }
-
-    public static final StoreMetadataNode createRecursively(final NormalizedNode<?, ?> node,
-            final UnsignedLong version) {
-        Builder builder = builder(version) //
-                .setSubtreeVersion(version) //
-                .setData(node);
-        if (node instanceof NormalizedNodeContainer<?, ?, ?>) {
-
-            @SuppressWarnings("unchecked")
-            NormalizedNodeContainer<?, ?, NormalizedNode<?, ?>> nodeContainer = (NormalizedNodeContainer<?, ?, NormalizedNode<?, ?>>) node;
-            for (NormalizedNode<?, ?> subNode : nodeContainer.getValue()) {
-                builder.add(createRecursively(subNode, version));
-            }
-        }
-        return builder.build();
-    }
-
-    public static class Builder {
-
-        private final UnsignedLong nodeVersion;
-        private UnsignedLong subtreeVersion;
-        private NormalizedNode<?, ?> data;
-        private Map<PathArgument, StoreMetadataNode> children;
-        private boolean dirty = false;
-
-        private Builder(final UnsignedLong version) {
-            this.nodeVersion = Preconditions.checkNotNull(version);
-            children = new HashMap<>();
-        }
-
-        private Builder(final StoreMetadataNode node) {
-            this.nodeVersion = node.getNodeVersion();
-            children = new HashMap<>(node.children);
-        }
-
-        public Builder setSubtreeVersion(final UnsignedLong version) {
-            this.subtreeVersion = version;
-            return this;
-        }
-
-        public Builder setData(final NormalizedNode<?, ?> data) {
-            this.data = data;
-            return this;
-        }
-
-        public Builder add(final StoreMetadataNode node) {
-            if (dirty) {
-                children = new HashMap<>(children);
-                dirty = false;
-            }
-            children.put(node.getIdentifier(), node);
-            return this;
-        }
-
-        public Builder remove(final PathArgument id) {
-            if (dirty) {
-                children = new HashMap<>(children);
-                dirty = false;
-            }
-            children.remove(id);
-            return this;
-        }
-
-        public StoreMetadataNode build() {
-            checkState(data != null, "Data node should not be null.");
-            checkState(subtreeVersion.compareTo(nodeVersion) >= 0,
-                    "Subtree version must be equals or greater than node version.");
-            dirty = true;
-            return new StoreMetadataNode(data, nodeVersion, subtreeVersion, children);
-        }
-    }
-
-}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/StoreNodeCompositeBuilder.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/StoreNodeCompositeBuilder.java
deleted file mode 100644 (file)
index 19debbb..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
-
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
-
-import com.google.common.base.Preconditions;
-import com.google.common.primitives.UnsignedLong;
-
-/**
- *
- * Helper builder
- *
- *
- */
-@SuppressWarnings("rawtypes")
-class StoreNodeCompositeBuilder {
-
-    private final StoreMetadataNode.Builder metadata;
-
-    private final NormalizedNodeContainerBuilder data;
-
-    private StoreNodeCompositeBuilder(final UnsignedLong version, final NormalizedNodeContainerBuilder nodeBuilder) {
-        this.metadata = StoreMetadataNode.builder(version);
-        this.data = Preconditions.checkNotNull(nodeBuilder);
-    }
-
-    private StoreNodeCompositeBuilder(final NormalizedNodeContainerBuilder nodeBuilder, final StoreMetadataNode currentMeta) {
-        this.metadata = StoreMetadataNode.builder(currentMeta);
-        this.data = Preconditions.checkNotNull(nodeBuilder);
-    }
-
-    @SuppressWarnings("unchecked")
-    public StoreNodeCompositeBuilder add(final StoreMetadataNode node) {
-        metadata.add(node);
-        data.addChild(node.getData());
-        return this;
-    }
-
-    @SuppressWarnings("unchecked")
-    public StoreNodeCompositeBuilder remove(final PathArgument id) {
-        metadata.remove(id);
-        data.removeChild(id);
-        return this;
-    }
-
-    public StoreMetadataNode build() {
-        return metadata.setData(data.build()).build();
-    }
-
-    public static StoreNodeCompositeBuilder create(final UnsignedLong version, final NormalizedNodeContainerBuilder nodeBuilder) {
-        return new StoreNodeCompositeBuilder(version, nodeBuilder);
-    }
-
-    public static StoreNodeCompositeBuilder create(final NormalizedNodeContainerBuilder nodeBuilder, final StoreMetadataNode currentMeta) {
-        return new StoreNodeCompositeBuilder(nodeBuilder, currentMeta);
-    }
-
-    @SuppressWarnings("unchecked")
-    public StoreNodeCompositeBuilder setIdentifier(final PathArgument identifier) {
-        data.withNodeIdentifier(identifier);
-        return this;
-    }
-
-    public StoreNodeCompositeBuilder setSubtreeVersion(final UnsignedLong updatedSubtreeVersion) {
-        metadata.setSubtreeVersion(updatedSubtreeVersion);
-        return this;
-    }
-}
index 28929539359fb94807c54000fe24c6151ff8eddd..6250b307026b72a2f480f2646e236e2ddf7e1440 100644 (file)
@@ -4,82 +4,85 @@
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
- */package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
+ */
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
 
- import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkArgument;
 
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataPreconditionFailedException;
- import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
- import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
- import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
- import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
- import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
- import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
- import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
- import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNodeFactory;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
 
 import com.google.common.base.Optional;
- import com.google.common.primitives.UnsignedLong;
+import com.google.common.primitives.UnsignedLong;
 
- abstract class ValueNodeModificationStrategy<T extends DataSchemaNode> extends SchemaAwareApplyOperation {
+abstract class ValueNodeModificationStrategy<T extends DataSchemaNode> extends SchemaAwareApplyOperation {
 
-     private final T schema;
-     private final Class<? extends NormalizedNode<?, ?>> nodeClass;
+    private final T schema;
+    private final Class<? extends NormalizedNode<?, ?>> nodeClass;
 
-     protected ValueNodeModificationStrategy(final T schema, final Class<? extends NormalizedNode<?, ?>> nodeClass) {
-         super();
-         this.schema = schema;
-         this.nodeClass = nodeClass;
-     }
+    protected ValueNodeModificationStrategy(final T schema, final Class<? extends NormalizedNode<?, ?>> nodeClass) {
+        super();
+        this.schema = schema;
+        this.nodeClass = nodeClass;
+    }
 
-     @Override
-     protected void verifyWrittenStructure(final NormalizedNode<?, ?> writtenValue) {
-         checkArgument(nodeClass.isInstance(writtenValue), "Node should must be of type %s", nodeClass);
-     }
+    @Override
+    protected void verifyWrittenStructure(final NormalizedNode<?, ?> writtenValue) {
+        checkArgument(nodeClass.isInstance(writtenValue), "Node should must be of type %s", nodeClass);
+    }
 
-     @Override
-     public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
-         throw new UnsupportedOperationException("Node " + schema.getPath()
-                 + "is leaf type node. Child nodes not allowed");
-     }
+    @Override
+    public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
+        throw new UnsupportedOperationException("Node " + schema.getPath()
+                + "is leaf type node. Child nodes not allowed");
+    }
 
-     @Override
-     protected StoreMetadataNode applySubtreeChange(final NodeModification modification,
-             final StoreMetadataNode currentMeta, final UnsignedLong subtreeVersion) {
-         throw new UnsupportedOperationException("Node " + schema.getPath()
-                 + "is leaf type node. Subtree change is not allowed.");
-     }
+    @Override
+    protected TreeNode applySubtreeChange(final ModifiedNode modification,
+            final TreeNode currentMeta, final UnsignedLong subtreeVersion) {
+        throw new UnsupportedOperationException("Node " + schema.getPath()
+                + "is leaf type node. Subtree change is not allowed.");
+    }
 
-     @Override
-     protected StoreMetadataNode applyMerge(final NodeModification modification, final StoreMetadataNode currentMeta,
-             final UnsignedLong subtreeVersion) {
-         return applyWrite(modification, Optional.of(currentMeta), subtreeVersion);
-     }
+    @Override
+    protected TreeNode applyMerge(final ModifiedNode modification, final TreeNode currentMeta,
+            final UnsignedLong subtreeVersion) {
+        // Just overwrite whatever was there
+        return applyWrite(modification, null, subtreeVersion);
+    }
 
-     @Override
-     protected StoreMetadataNode applyWrite(final NodeModification modification,
-             final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
-         return StoreMetadataNode.builder(subtreeVersion).setSubtreeVersion(subtreeVersion)
-                 .setData(modification.getWrittenValue()).build();
-     }
+    @Override
+    protected TreeNode applyWrite(final ModifiedNode modification,
+            final Optional<TreeNode> currentMeta, final UnsignedLong subtreeVersion) {
+        return TreeNodeFactory.createTreeNode(modification.getWrittenValue(), subtreeVersion);
+    }
 
-     @Override
-     protected void checkSubtreeModificationApplicable(final InstanceIdentifier path,final NodeModification modification,
-             final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
-         throw new DataPreconditionFailedException(path, "Subtree modification is not allowed.");
-     }
+    @Override
+    protected void checkSubtreeModificationApplicable(final InstanceIdentifier path, final NodeModification modification,
+            final Optional<TreeNode> current) throws DataPreconditionFailedException {
+        throw new DataPreconditionFailedException(path, "Subtree modification is not allowed.");
+    }
 
-     public static class LeafSetEntryModificationStrategy extends ValueNodeModificationStrategy<LeafListSchemaNode> {
-         @SuppressWarnings({ "unchecked", "rawtypes" })
-         protected LeafSetEntryModificationStrategy(final LeafListSchemaNode schema) {
-             super(schema, (Class) LeafSetEntryNode.class);
-         }
-     }
+    public static class LeafSetEntryModificationStrategy extends ValueNodeModificationStrategy<LeafListSchemaNode> {
+        @SuppressWarnings({ "unchecked", "rawtypes" })
+        protected LeafSetEntryModificationStrategy(final LeafListSchemaNode schema) {
+            super(schema, (Class) LeafSetEntryNode.class);
+        }
+    }
 
-     public static class LeafModificationStrategy extends ValueNodeModificationStrategy<LeafSchemaNode> {
-         @SuppressWarnings({ "unchecked", "rawtypes" })
-         protected LeafModificationStrategy(final LeafSchemaNode schema) {
-             super(schema, (Class) LeafNode.class);
-         }
-     }
- }
\ No newline at end of file
+    public static class LeafModificationStrategy extends ValueNodeModificationStrategy<LeafSchemaNode> {
+        @SuppressWarnings({ "unchecked", "rawtypes" })
+        protected LeafModificationStrategy(final LeafSchemaNode schema) {
+            super(schema, (Class) LeafNode.class);
+        }
+    }
+}
\ No newline at end of file
index 8940e55d321cbd57a6c80e6c1fe0a5c04255569e..abaa4d1eca00e1756a1bba0b2a8a9f434f970eeb 100644 (file)
@@ -29,6 +29,7 @@ import org.junit.Test;
 import org.opendaylight.controller.md.sal.dom.store.impl.TestModel;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTree;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeModification;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNodeFactory;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
@@ -149,7 +150,7 @@ public class ModificationMetadataTreeTest {
     @Test
     public void basicReadWrites() {
         DataTreeModification modificationTree = new InMemoryDataTreeModification(new InMemoryDataTreeSnapshot(schemaContext,
-                StoreMetadataNode.createRecursively(createDocumentOne(), UnsignedLong.valueOf(5)), applyOper),
+                TreeNodeFactory.createTreeNode(createDocumentOne(), UnsignedLong.valueOf(5)), applyOper),
                 new SchemaAwareApplyOperationRoot(schemaContext));
         Optional<NormalizedNode<?, ?>> originalBarNode = modificationTree.readNode(OUTER_LIST_2_PATH);
         assertTrue(originalBarNode.isPresent());