Merge "Bug 1036 - Allow using container in case stmt to preserve uniqueness."
[controller.git] / opendaylight / md-sal / sal-dom-broker / src / main / java / org / opendaylight / controller / md / sal / dom / store / impl / tree / spi / ContainerNode.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.controller.md.sal.dom.store.impl.tree.spi;
9
10 import java.util.Collections;
11 import java.util.HashMap;
12 import java.util.Map;
13
14 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
15 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
16 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
17 import org.opendaylight.yangtools.yang.data.api.schema.OrderedNodeContainer;
18
19 import com.google.common.base.Optional;
20 import com.google.common.base.Preconditions;
21
22 /**
23  * A TreeNode capable of holding child nodes. The fact that any of the children
24  * changed is tracked by the subtree version.
25  */
26 final class ContainerNode extends AbstractTreeNode {
27     private final Map<PathArgument, TreeNode> children;
28     private final Version subtreeVersion;
29
30     protected ContainerNode(final NormalizedNode<?, ?> data, final Version version,
31             final Map<PathArgument, TreeNode> children, final Version subtreeVersion) {
32         super(data, version);
33         this.children = Preconditions.checkNotNull(children);
34         this.subtreeVersion = Preconditions.checkNotNull(subtreeVersion);
35     }
36
37     @Override
38     public Version getSubtreeVersion() {
39         return subtreeVersion;
40     }
41
42     @Override
43     public Optional<TreeNode> getChild(final PathArgument key) {
44         return Optional.fromNullable(children.get(key));
45     }
46
47     @Override
48     public MutableTreeNode mutable() {
49         return new Mutable(this);
50     }
51
52     private static final class Mutable implements MutableTreeNode {
53         private final Map<PathArgument, TreeNode> children;
54         private final Version version;
55         private NormalizedNode<?, ?> data;
56         private Version subtreeVersion;
57
58         private Mutable(final ContainerNode parent) {
59             this.data = parent.getData();
60             this.children = new HashMap<>(parent.children);
61             this.subtreeVersion = parent.getSubtreeVersion();
62             this.version = parent.getVersion();
63         }
64
65         @Override
66         public Optional<TreeNode> getChild(final PathArgument child) {
67             return Optional.fromNullable(children.get(child));
68         }
69
70         @Override
71         public void setSubtreeVersion(final Version subtreeVersion) {
72             this.subtreeVersion = Preconditions.checkNotNull(subtreeVersion);
73         }
74
75         @Override
76         public void addChild(final TreeNode child) {
77             children.put(child.getIdentifier(), child);
78         }
79
80         @Override
81         public void removeChild(final PathArgument id) {
82             children.remove(id);
83         }
84
85         @Override
86         public TreeNode seal() {
87             final Map<PathArgument, TreeNode> realChildren;
88
89             if (children.isEmpty()) {
90                 realChildren = Collections.emptyMap();
91             } else {
92                 realChildren = children;
93             }
94
95             return new ContainerNode(data, version, realChildren, subtreeVersion);
96         }
97
98         @Override
99         public void setData(final NormalizedNode<?, ?> data) {
100             this.data = Preconditions.checkNotNull(data);
101         }
102     }
103
104     private static ContainerNode create(final Version version, final NormalizedNode<?, ?> data,
105             final Iterable<NormalizedNode<?, ?>> children) {
106         final Map<PathArgument, TreeNode> map = new HashMap<>();
107
108         for (NormalizedNode<?, ?> child : children) {
109             map.put(child.getIdentifier(), TreeNodeFactory.createTreeNode(child, version));
110         }
111
112         return new ContainerNode(data, version, map, version);
113     }
114
115     public static ContainerNode create(final Version version, final NormalizedNodeContainer<?, ?, NormalizedNode<?, ?>> container) {
116         return create(version, container, container.getValue());
117     }
118
119     public static ContainerNode create(final Version version, final OrderedNodeContainer<NormalizedNode<?, ?>> container) {
120         return create(version, container, container.getValue());
121     }
122 }