Merge "BUG-509: create data tree SPI package"
authorTony Tkacik <ttkacik@cisco.com>
Fri, 23 May 2014 13:56:42 +0000 (13:56 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Fri, 23 May 2014 13:56:42 +0000 (13:56 +0000)
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/AbstractTreeNode.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/ContainerNode.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/MutableTreeNode.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/TreeNode.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/TreeNodeFactory.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/ValueNode.java [new file with mode: 0644]

diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/AbstractTreeNode.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/AbstractTreeNode.java
new file mode 100644 (file)
index 0000000..1cf28a3
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * 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.spi;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+import com.google.common.base.Preconditions;
+import com.google.common.primitives.UnsignedLong;
+
+/*
+ * A very basic data tree node.
+ */
+abstract class AbstractTreeNode implements TreeNode {
+    private final NormalizedNode<?, ?> data;
+    private final UnsignedLong version;
+
+    protected AbstractTreeNode(final NormalizedNode<?, ?> data, final UnsignedLong version) {
+        this.data = Preconditions.checkNotNull(data);
+        this.version = Preconditions.checkNotNull(version);
+    }
+
+    @Override
+    public PathArgument getIdentifier() {
+        return data.getIdentifier();
+    }
+
+    @Override
+    public final UnsignedLong getVersion() {
+        return version;
+    }
+
+    @Override
+    public final NormalizedNode<?, ?> getData() {
+        return data;
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/ContainerNode.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/ContainerNode.java
new file mode 100644 (file)
index 0000000..20bf619
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * 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.spi;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+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 org.opendaylight.yangtools.yang.data.api.schema.OrderedNodeContainer;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.primitives.UnsignedLong;
+
+/**
+ * A TreeNode capable of holding child nodes. The fact that any of the children
+ * changed is tracked by the subtree version.
+ */
+final class ContainerNode extends AbstractTreeNode {
+    private final Map<PathArgument, TreeNode> children;
+    private final UnsignedLong subtreeVersion;
+
+    protected ContainerNode(final NormalizedNode<?, ?> data, final UnsignedLong version,
+            final Map<PathArgument, TreeNode> children, final UnsignedLong subtreeVersion) {
+        super(data, version);
+        this.children = Preconditions.checkNotNull(children);
+        this.subtreeVersion = Preconditions.checkNotNull(subtreeVersion);
+    }
+
+    @Override
+    public UnsignedLong getSubtreeVersion() {
+        return subtreeVersion;
+    }
+
+    @Override
+    public Optional<TreeNode> getChild(final PathArgument key) {
+        return Optional.fromNullable(children.get(key));
+    }
+
+    @Override
+    public MutableTreeNode mutable() {
+        return new Mutable(this);
+    }
+
+    private static final class Mutable implements MutableTreeNode {
+        private final Map<PathArgument, TreeNode> children;
+        private final UnsignedLong version;
+        private NormalizedNode<?, ?> data;
+        private UnsignedLong subtreeVersion;
+
+        private Mutable(final ContainerNode parent) {
+            this.data = parent.getData();
+            this.children = new HashMap<>(parent.children);
+            this.subtreeVersion = parent.getSubtreeVersion();
+            this.version = parent.getVersion();
+        }
+
+        @Override
+        public Optional<TreeNode> getChild(final PathArgument child) {
+            return Optional.fromNullable(children.get(child));
+        }
+
+        @Override
+        public void setSubtreeVersion(final UnsignedLong subtreeVersion) {
+            this.subtreeVersion = Preconditions.checkNotNull(subtreeVersion);
+        }
+
+        @Override
+        public void addChild(final TreeNode child) {
+            children.put(child.getIdentifier(), child);
+        }
+
+        @Override
+        public void removeChild(final PathArgument id) {
+            children.remove(id);
+        }
+
+        @Override
+        public TreeNode seal() {
+            final Map<PathArgument, TreeNode> realChildren;
+
+            if (children.isEmpty()) {
+                realChildren = Collections.emptyMap();
+            } else {
+                realChildren = children;
+            }
+
+            return new ContainerNode(data, version, realChildren, subtreeVersion);
+        }
+
+        @Override
+        public void setData(final NormalizedNode<?, ?> data) {
+            this.data = Preconditions.checkNotNull(data);
+        }
+    }
+
+    private static ContainerNode create(final UnsignedLong version, final NormalizedNode<?, ?> data, final Iterable<NormalizedNode<?, ?>> children) {
+        final Map<PathArgument, TreeNode> map = new HashMap<>();
+
+        for (NormalizedNode<?, ?> child : children) {
+            map.put(child.getIdentifier(), TreeNodeFactory.createTreeNode(child, version));
+        }
+
+        return new ContainerNode(data, version, map, version);
+    }
+
+    public static ContainerNode create(final UnsignedLong version, final NormalizedNodeContainer<?, ?, NormalizedNode<?, ?>> container) {
+        return create(version, container, container.getValue());
+    }
+
+    public static ContainerNode create(final UnsignedLong version, final OrderedNodeContainer<NormalizedNode<?, ?>> container) {
+        return create(version, container, container.getValue());
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/MutableTreeNode.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/MutableTreeNode.java
new file mode 100644 (file)
index 0000000..84300a9
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * 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.spi;
+
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreTreeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+import com.google.common.primitives.UnsignedLong;
+
+public interface MutableTreeNode extends StoreTreeNode<TreeNode> {
+    void setData(NormalizedNode<?, ?> data);
+    void setSubtreeVersion(UnsignedLong subtreeVersion);
+    void addChild(TreeNode child);
+    void removeChild(PathArgument id);
+    TreeNode seal();
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/TreeNode.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/TreeNode.java
new file mode 100644 (file)
index 0000000..e3c3591
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * 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.spi;
+
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreTreeNode;
+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.primitives.UnsignedLong;
+
+/*
+ * A very basic data tree node. It has a version (when it was last modified),
+ * a subtree version (when any of its children were modified) and some read-only
+ * data.
+ */
+public interface TreeNode extends Identifiable<PathArgument>, StoreTreeNode<TreeNode> {
+    /**
+     * Get the data node version.
+     *
+     * @return Current data node version.
+     */
+    UnsignedLong getVersion();
+
+    /**
+     * Get the subtree version.
+     *
+     * @return Current subtree version.
+     */
+    UnsignedLong getSubtreeVersion();
+
+    /**
+     * Get a read-only view of the underlying data.
+     *
+     * @return Unmodifiable view of the underlying data.
+     */
+    NormalizedNode<?, ?> getData();
+
+    /**
+     * Get a mutable, isolated copy of the node.
+     *
+     * @return Mutable copy
+     */
+    MutableTreeNode mutable();
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/TreeNodeFactory.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/TreeNodeFactory.java
new file mode 100644 (file)
index 0000000..03c3ab8
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * 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.spi;
+
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
+import org.opendaylight.yangtools.yang.data.api.schema.OrderedNodeContainer;
+
+import com.google.common.primitives.UnsignedLong;
+
+public final class TreeNodeFactory {
+    private TreeNodeFactory() {
+        throw new UnsupportedOperationException("Utility class should not be instantiated");
+    }
+
+    /**
+     * Create a new AbstractTreeNode from a data node, descending recursively as needed.
+     * This method should only ever be used for new data.
+     *
+     * @param data data node
+     * @param version data node version
+     * @return new AbstractTreeNode instance, covering the data tree provided
+     */
+    public static final TreeNode createTreeNode(final NormalizedNode<?, ?> data, final UnsignedLong version) {
+        if (data instanceof NormalizedNodeContainer<?, ?, ?>) {
+            @SuppressWarnings("unchecked")
+            NormalizedNodeContainer<?, ?, NormalizedNode<?, ?>> container = (NormalizedNodeContainer<?, ?, NormalizedNode<?, ?>>) data;
+            return ContainerNode.create(version, container);
+
+        }
+        if (data instanceof OrderedNodeContainer<?>) {
+            @SuppressWarnings("unchecked")
+            OrderedNodeContainer<NormalizedNode<?, ?>> container = (OrderedNodeContainer<NormalizedNode<?, ?>>) data;
+            return ContainerNode.create(version, container);
+        }
+
+        return new ValueNode(data, version);
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/ValueNode.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/ValueNode.java
new file mode 100644 (file)
index 0000000..cbd2a17
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * 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.spi;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.primitives.UnsignedLong;
+
+final class ValueNode extends AbstractTreeNode {
+    private static final Logger LOG = LoggerFactory.getLogger(ValueNode.class);
+
+    protected ValueNode(final NormalizedNode<?, ?> data, final UnsignedLong version) {
+        super(data, version);
+    }
+
+    @Override
+    public Optional<TreeNode> getChild(final PathArgument childId) {
+        LOG.warn("Attempted to access child {} of value-node {}", childId, this);
+        return Optional.absent();
+    }
+
+    @Override
+    public UnsignedLong getSubtreeVersion() {
+        return getVersion();
+    }
+
+    @Override
+    public MutableTreeNode mutable() {
+        /**
+         * Value nodes can only we read/written/delete, which does a straight
+         * replace. That means they don't haver need to be made mutable.
+         */
+        throw new UnsupportedOperationException(String.format("Attempted to mutate value-node %s", this));
+    }
+}